| /******************************************************************************* |
| * Copyright (c) 2002 IBM Corp. and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.jdt.core.tests.model; |
| |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| |
| import org.eclipse.jdt.core.*; |
| import org.eclipse.jdt.internal.core.JavaProject; |
| |
| import java.io.IOException; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| public class ClasspathTests extends ModifyingResourceTests { |
| |
| public class TestContainer implements IClasspathContainer { |
| IPath path; |
| IClasspathEntry[] entries; |
| TestContainer(IPath path, IClasspathEntry[] entries){ |
| this.path = path; |
| this.entries = entries; |
| } |
| public IPath getPath() { return this.path; } |
| public IClasspathEntry[] getClasspathEntries() { return this.entries; } |
| public String getDescription() { return null; } |
| public int getKind() { return 0; } |
| }; |
| |
| public ClasspathTests(String name) { |
| super(name); |
| } |
| protected void assertCycleMarkers(IJavaProject project, IJavaProject[] p, int[] expectedCycleParticipants) throws CoreException { |
| 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()); |
| } |
| protected void assertMarkers(String message, String expectedMarkers, IJavaProject project) throws CoreException { |
| IMarker[] markers = project.getProject().findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ONE); |
| StringBuffer buffer = new StringBuffer(); |
| for (int i = 0, length = markers.length; i < length; i++) { |
| IMarker marker = markers[i]; |
| buffer.append(marker.getAttribute(IMarker.MESSAGE)); |
| if (i != length-1) { |
| buffer.append("\n"); |
| } |
| } |
| assertEquals(message, expectedMarkers, buffer.toString()); |
| } |
| protected int numberOfCycleMarkers(IJavaProject javaProject) throws CoreException { |
| IMarker[] markers = javaProject.getProject().findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ONE); |
| int result = 0; |
| for (int i = 0, length = markers.length; i < length; i++) { |
| IMarker marker = markers[i]; |
| String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED); |
| if (cycleAttr != null && cycleAttr.equals("true")){ //$NON-NLS-1$ |
| result++; |
| } |
| } |
| return result; |
| } |
| |
| public static Test suite() { |
| |
| if (false){ |
| TestSuite suite = new Suite(ClasspathTests.class.getName()); |
| suite.addTest(new ClasspathTests("testDenseCycleDetection")); |
| return suite; |
| } |
| return new Suite(ClasspathTests.class); |
| } |
| /** |
| * Add an entry to the classpath for a non-existent root. Then create |
| * the root and ensure that it comes alive. |
| */ |
| public void testClasspathAddRoot() throws JavaModelException, CoreException, IOException { |
| IJavaProject project = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalCP= project.getRawClasspath(); |
| |
| try { |
| IClasspathEntry newEntry= JavaCore.newSourceEntry(project.getProject().getFullPath().append("extra")); |
| |
| IClasspathEntry[] newCP= new IClasspathEntry[originalCP.length + 1]; |
| System.arraycopy(originalCP, 0 , newCP, 0, originalCP.length); |
| newCP[originalCP.length]= newEntry; |
| |
| project.setRawClasspath(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"); |
| } |
| } |
| /** |
| * Ensures that the reordering external resources in the classpath |
| * generates the correct deltas. |
| */ |
| public void testClasspathChangeExternalResources() throws CoreException { |
| try { |
| IJavaProject proj = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalCP = proj.getRawClasspath(); |
| IPackageFragmentRoot root = getPackageFragmentRoot("P", "src"); |
| |
| IClasspathEntry[] newEntries = new IClasspathEntry[2]; |
| newEntries[0] = JavaCore.newLibraryEntry(new Path(getExternalJCLPath()), null, null, false); |
| newEntries[1] = JavaCore.newLibraryEntry(new Path(getExternalJCLSourcePath()), null, null, false); |
| setClasspath(proj, newEntries); |
| startDeltas(); |
| IClasspathEntry[] swappedEntries = new IClasspathEntry[2]; |
| swappedEntries[0] = newEntries[1]; |
| swappedEntries[1] = newEntries[0]; |
| setClasspath(proj, swappedEntries); |
| assertTrue("should be one delta - two jars reordered", this.deltaListener.deltas.length == 1); |
| IJavaElementDelta d = getDeltaFor(proj); |
| assertTrue("should be a delta for the project", d != null); |
| } finally { |
| stopDeltas(); |
| this.deleteProject("P"); |
| } |
| } |
| |
| /** |
| * 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 { |
| IJavaProject proj = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| this.createFile("P/src/X.java", "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.getCompilationUnits().length); |
| assertEquals( |
| "Unexpected numbers of .class files", |
| 0, |
| pkg.getClassFiles().length); |
| |
| this.setClasspath( |
| proj, |
| new IClasspathEntry[] { |
| JavaCore.newLibraryEntry(rootFolder.getFullPath(), null, null, false) |
| }); |
| assertEquals( |
| "Unexpected root kind 2", |
| IPackageFragmentRoot.K_BINARY, |
| root.getKind()); |
| assertEquals( |
| "Unexpected numbers of compilation units", |
| 0, |
| pkg.getCompilationUnits().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 { |
| IJavaProject proj = this.createJavaProject("P", new String[] {""}, ""); |
| IPackageFragmentRoot root = getPackageFragmentRoot("P", ""); |
| IClasspathEntry[] originalCP= proj.getRawClasspath(); |
| IClasspathEntry newEntry= JavaCore.newLibraryEntry(new Path(getExternalJCLPath()), null, null, false); |
| IClasspathEntry[] newEntries= new IClasspathEntry[]{newEntry}; |
| IPackageFragmentRoot newRoot= proj.getPackageFragmentRoot(getExternalJCLPath()); |
| |
| 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); |
| IJavaElementDelta d= null; |
| assertTrue("root should be removed from classpath",(d= getDeltaFor(root, true)) != null && |
| (d.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0); |
| |
| |
| assertTrue("root should be added to classpath", (d= getDeltaFor(newRoot, true)) != null && |
| (d.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0); |
| } finally { |
| stopDeltas(); |
| |
| this.deleteProject("P"); |
| } |
| } |
| |
| /** |
| * Tests the cross project classpath setting |
| */ |
| public void testClasspathCrossProject() throws JavaModelException, CoreException { |
| IJavaProject project = this.createJavaProject("P1", new String[] {""}, ""); |
| this.createJavaProject("P2", new String[] {}, ""); |
| IClasspathEntry[] oldClasspath= project.getRawClasspath(); |
| try { |
| startDeltas(); |
| IPackageFragmentRoot oldRoot= getPackageFragmentRoot("P1", ""); |
| IClasspathEntry projectEntry= JavaCore.newProjectEntry(new Path("/P2"), false); |
| IClasspathEntry[] newClasspath= new IClasspathEntry[]{projectEntry}; |
| project.setRawClasspath(newClasspath, null); |
| project.getAllPackageFragmentRoots(); |
| IJavaElementDelta removedDelta= getDeltaFor(oldRoot, true); |
| assertTrue("Deltas not correct for crossproject classpath setting", |
| this.deltaListener.deltas.length == 1 && |
| this.deltaListener.deltas[0].getAffectedChildren().length == 1 && |
| removedDelta.getElement().equals(oldRoot) && |
| removedDelta.getKind() == IJavaElementDelta.CHANGED && |
| (removedDelta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0 |
| ); |
| } finally { |
| stopDeltas(); |
| this.deleteProject("P1"); |
| this.deleteProject("P2"); |
| } |
| } |
| /** |
| * Delete a root and ensure the classpath is not updated (i.e. entry isn't removed). |
| */ |
| public void testClasspathDeleteNestedRoot() throws JavaModelException, CoreException, IOException { |
| IJavaProject project = this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPath()}, "bin"); |
| IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src"); |
| IClasspathEntry[] originalCP= project.getRawClasspath(); |
| |
| // delete the root |
| IFolder folder= (IFolder)root.getUnderlyingResource(); |
| root.getUnderlyingResource().delete(false, null); |
| |
| IClasspathEntry[] newCP= project.getRawClasspath(); |
| |
| 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"); |
| } |
| } |
| /** |
| * Delete a nested root's parent folder and ensure the classpath is |
| * not updated (i.e. entry isn't removed). |
| */ |
| public void testClasspathDeleteNestedRootParent() throws JavaModelException, CoreException, IOException { |
| IJavaProject project = this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPath()}, "bin"); |
| IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src"); |
| IClasspathEntry[] originalCP= project.getRawClasspath(); |
| |
| // delete the root's parent folder |
| IFolder folder= (IFolder)root.getUnderlyingResource().getParent(); |
| folder.delete(false, null); |
| |
| IClasspathEntry[] newCP= project.getRawClasspath(); |
| |
| 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 { |
| IJavaProject project= this.createJavaProject("P", new String[] {}, new String[] {getExternalJCLPath()}, ""); |
| IClasspathEntry[] classpath= project.getRawClasspath(); |
| IClasspathEntry jar= null; |
| for (int i= 0; i < classpath.length; i++) { |
| if (classpath[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) { |
| jar= classpath[i]; |
| break; |
| } |
| } |
| project.close(); |
| project.open(null); |
| |
| classpath= project.getRawClasspath(); |
| for (int i= 0; i < classpath.length; i++) { |
| if (classpath[i].getEntryKind() == IClasspathEntry.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 JavaModelException, CoreException, IOException { |
| IJavaProject project = this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPath()}, "bin"); |
| IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src"); |
| IClasspathEntry[] originalCP= project.getRawClasspath(); |
| |
| // 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); |
| |
| IClasspathEntry[] newCP= project.getRawClasspath(); |
| |
| 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])); |
| |
| IJavaElementDelta rootDelta = getDeltaFor(root, true); |
| IJavaElementDelta projectDelta = getDeltaFor(newRoot.getParent(), true); |
| assertTrue("should get delta for moved root", rootDelta != null && |
| rootDelta.getKind() == IJavaElementDelta.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 JavaModelException, CoreException, IOException { |
| try { |
| IJavaProject project =this.createJavaProject("P", new String[] {"nested/src"}, new String[] {getExternalJCLPath()}, "bin"); |
| IPackageFragmentRoot root= getPackageFragmentRoot("P", "nested/src"); |
| IClasspathEntry[] originalCP= project.getRawClasspath(); |
| |
| // 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); |
| |
| IClasspathEntry[] newCP= project.getRawClasspath(); |
| |
| // 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 JavaModelException, CoreException { |
| try { |
| IJavaProject classFileProject= this.createJavaProject("P", new String[] {""}, ""); |
| IClasspathEntry[] oldClasspath= classFileProject.getRawClasspath(); |
| startDeltas(); |
| classFileProject.setRawClasspath(oldClasspath, null); |
| assertTrue("No deltas should be generated for the same classpath", |
| this.deltaListener.deltas.length == 0); |
| } finally { |
| stopDeltas(); |
| this.deleteProject("P"); |
| } |
| } |
| /** |
| * Ensures that the setting the classpath with a reordered classpath generates |
| * the correct deltas. |
| */ |
| public void testClasspathReordering() throws CoreException { |
| IJavaProject proj = this.createJavaProject("P", new String[] {"src"}, new String[] {getExternalJCLPath()}, "bin"); |
| IClasspathEntry[] originalCP = proj.getRawClasspath(); |
| IPackageFragmentRoot root = getPackageFragmentRoot("P", "src"); |
| try { |
| IClasspathEntry[] newEntries = new IClasspathEntry[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); |
| IJavaElementDelta d = null; |
| assertTrue("root should be reordered in the classpath", (d = getDeltaFor(root, true)) != null |
| && (d.getFlags() & IJavaElementDelta.F_CLASSPATH_REORDER) > 0); |
| } finally { |
| stopDeltas(); |
| this.deleteProject("P"); |
| } |
| } |
| |
| /** |
| * Should detect duplicate entries on the classpath |
| */ |
| public void testClasspathValidation1() throws CoreException { |
| try { |
| IJavaProject proj = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalCP = proj.getRawClasspath(); |
| |
| IClasspathEntry[] newCP = new IClasspathEntry[originalCP.length+1]; |
| System.arraycopy(originalCP, 0, newCP, 0, originalCP.length); |
| newCP[originalCP.length] = newCP[0]; |
| |
| IJavaModelStatus status = JavaConventions.validateClasspath(proj, newCP, proj.getOutputLocation()); |
| |
| assertTrue("should have detected duplicate entries on the classpath", !status.isOK()); |
| } finally { |
| this.deleteProject("P"); |
| } |
| } |
| |
| /** |
| * Should detect nested source folders on the classpath |
| */ |
| public void testClasspathValidation2() throws CoreException { |
| try { |
| IJavaProject proj = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalCP = proj.getRawClasspath(); |
| |
| IClasspathEntry[] newCP = new IClasspathEntry[originalCP.length+1]; |
| System.arraycopy(originalCP, 0, newCP, 0, originalCP.length); |
| newCP[originalCP.length] = JavaCore.newSourceEntry(new Path("/P")); |
| |
| IJavaModelStatus status = JavaConventions.validateClasspath(proj, newCP, proj.getOutputLocation()); |
| |
| assertTrue("should have detected nested source folders on the classpath", !status.isOK()); |
| } finally { |
| this.deleteProject("P"); |
| } |
| } |
| |
| /** |
| * Should detect library folder nested inside source folder on the classpath |
| */ |
| public void testClasspathValidation3() throws CoreException { |
| try { |
| IJavaProject proj = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalCP = proj.getRawClasspath(); |
| |
| IClasspathEntry[] newCP = new IClasspathEntry[originalCP.length+1]; |
| System.arraycopy(originalCP, 0, newCP, 0, originalCP.length); |
| newCP[originalCP.length] = JavaCore.newLibraryEntry(new Path("/P/src/lib"), null, null); |
| |
| IJavaModelStatus status = JavaConventions.validateClasspath(proj, newCP, proj.getOutputLocation()); |
| |
| assertTrue("should have detected library folder nested inside source folder on the classpath", !status.isOK()); |
| } finally { |
| this.deleteProject("P"); |
| } |
| } |
| |
| public void testClasspathValidation4() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {"src0"}, "bin0"), |
| this.createJavaProject("P1", new String[] {"src1"}, "bin1"), |
| }; |
| |
| JavaCore.setClasspathVariable("var", new Path("/P1"), null); |
| |
| IClasspathEntry[] newClasspath = new IClasspathEntry[]{ |
| JavaCore.newSourceEntry(new Path("/P0/src0")), |
| JavaCore.newVariableEntry(new Path("var/src1"), null, null), |
| }; |
| |
| // validate classpath |
| IJavaModelStatus status = JavaConventions.validateClasspath(p[0], newClasspath, p[0].getOutputLocation()); |
| assertTrue("should not detect external source folder through a variable on the classpath", status.isOK()); |
| |
| } finally { |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| |
| public void testClasspathValidation5() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {"src0", "src1"}, "bin0"), |
| this.createJavaProject("P1", new String[] {"src1"}, "bin1"), |
| }; |
| |
| JavaCore.setClasspathContainer( |
| new Path("container/default"), |
| new IJavaProject[]{ p[0] }, |
| new IClasspathContainer[] { |
| new TestContainer(new Path("container/default"), |
| new IClasspathEntry[]{ |
| JavaCore.newSourceEntry(new Path("/P0/src0")), |
| JavaCore.newVariableEntry(new Path("var/src1"), null, null) }) |
| }, |
| null); |
| |
| IClasspathEntry[] newClasspath = new IClasspathEntry[]{ |
| JavaCore.newSourceEntry(new Path("/P0/src1")), |
| JavaCore.newContainerEntry(new Path("container/default")), |
| }; |
| |
| // validate classpath |
| IJavaModelStatus status = JavaConventions.validateClasspath(p[0], newClasspath, p[0].getOutputLocation()); |
| assertTrue("should not have detected external source folder through a container on the classpath", status.isOK()); |
| |
| // validate classpath entry |
| status = JavaConventions.validateClasspathEntry(p[0], newClasspath[1], true); |
| assertTrue("should have detected external source folder through a container on the classpath", !status.isOK()); |
| |
| } finally { |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| |
| public void testClasspathValidation6() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {"src"}, "src"), |
| }; |
| |
| // validate classpath entry |
| IClasspathEntry[] newClasspath = new IClasspathEntry[]{ |
| JavaCore.newSourceEntry(new Path("/P0")), |
| JavaCore.newSourceEntry(new Path("/P0/src")), |
| }; |
| |
| IJavaModelStatus status = JavaConventions.validateClasspath(p[0], newClasspath, p[0].getOutputLocation()); |
| assertTrue("should have detected nested source folder", !status.isOK()); |
| } finally { |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| /** |
| * Setting the classpath with two entries specifying the same path |
| * should fail. |
| */ |
| public void testClasspathWithDuplicateEntries() throws CoreException { |
| try { |
| IJavaProject project = this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] cp= project.getRawClasspath(); |
| IClasspathEntry[] newCp= new IClasspathEntry[cp.length *2]; |
| System.arraycopy(cp, 0, newCp, 0, cp.length); |
| System.arraycopy(cp, 0, newCp, cp.length, cp.length); |
| try { |
| project.setRawClasspath(newCp, null); |
| } catch (JavaModelException jme) { |
| return; |
| } |
| assertTrue("Setting the classpath with two entries specifying the same path should fail", false); |
| } finally { |
| this.deleteProject("P"); |
| } |
| } |
| /** |
| * 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 { |
| IJavaProject project= this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalPath= project.getRawClasspath(); |
| IPackageFragmentRoot[] originalRoots= project.getPackageFragmentRoots(); |
| |
| IClasspathEntry[] newPath= new IClasspathEntry[originalPath.length + 1]; |
| System.arraycopy(originalPath, 0, newPath, 0, originalPath.length); |
| |
| IClasspathEntry newEntry= JavaCore.newLibraryEntry(new Path("c:/nothing/nozip.jar"), null, null, false); |
| newPath[originalPath.length]= newEntry; |
| |
| project.setRawClasspath(newPath, null); |
| |
| IClasspathEntry[] getPath= project.getRawClasspath(); |
| 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 { |
| IJavaProject project= this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalPath= project.getRawClasspath(); |
| IPackageFragmentRoot[] originalRoots= project.getPackageFragmentRoots(); |
| |
| IClasspathEntry[] newPath= new IClasspathEntry[originalPath.length + 1]; |
| System.arraycopy(originalPath, 0, newPath, 0, originalPath.length); |
| |
| IClasspathEntry newEntry= JavaCore.newProjectEntry(new Path("/NoProject"), false); |
| newPath[originalPath.length]= newEntry; |
| |
| project.setRawClasspath(newPath, null); |
| |
| IClasspathEntry[] getPath= project.getRawClasspath(); |
| 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 { |
| IJavaProject project= this.createJavaProject("P", new String[] {"src"}, "bin"); |
| IClasspathEntry[] originalPath= project.getRawClasspath(); |
| IPackageFragmentRoot[] originalRoots= project.getPackageFragmentRoots(); |
| |
| IClasspathEntry[] newPath= new IClasspathEntry[originalPath.length + 1]; |
| System.arraycopy(originalPath, 0, newPath, 0, originalPath.length); |
| |
| IClasspathEntry newEntry= JavaCore.newSourceEntry(new Path("/P/moreSource")); |
| newPath[originalPath.length]= newEntry; |
| |
| project.setRawClasspath(newPath, null); |
| |
| IClasspathEntry[] getPath= project.getRawClasspath(); |
| 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 JavaModelException, CoreException, IOException { |
| |
| try { |
| IJavaProject p1 = this.createJavaProject("P1", new String[] {""}, ""); |
| IJavaProject p2 = this.createJavaProject("P2", new String[] {""}, ""); |
| IJavaProject p3 = this.createJavaProject("P3", new String[] {""}, new String[] {}, new String[] {"/P2"}, ""); |
| |
| // Ensure no cycle reported |
| IJavaProject[] 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 |
| IClasspathEntry[] originalP1CP= p1.getRawClasspath(); |
| IClasspathEntry[] originalP2CP= p2.getRawClasspath(); |
| |
| // Add P1 as a prerequesite of P2 |
| int length = originalP2CP.length; |
| IClasspathEntry[] newCP= new IClasspathEntry[length + 1]; |
| System.arraycopy(originalP2CP, 0 , newCP, 0, length); |
| newCP[length]= JavaCore.newProjectEntry(p1.getProject().getFullPath(), false); |
| p2.setRawClasspath(newCP, null); |
| |
| // Add P3 as a prerequesite of P1 |
| length = originalP1CP.length; |
| newCP= new IClasspathEntry[length + 1]; |
| System.arraycopy(originalP1CP, 0 , newCP, 0, length); |
| newCP[length]= JavaCore.newProjectEntry(p3.getProject().getFullPath(), false); |
| p1.setRawClasspath(newCP, null); |
| |
| // Ensure a cycle is reported on one of the projects |
| // Ensure no cycle reported |
| cycleMarkerCount = 0; |
| for (int i = 0; i < projects.length; i++){ |
| cycleMarkerCount += this.numberOfCycleMarkers(projects[i]); |
| } |
| assertTrue("Should have 3 projects involved in a classpath cycle", cycleMarkerCount == 3); |
| |
| } finally { |
| // cleanup |
| this.deleteProject("P1"); |
| this.deleteProject("P2"); |
| this.deleteProject("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 { |
| IJavaProject project = this.createJavaProject("P", new String[] {""}, "bin"); |
| IClasspathEntry[] classpath = project.getRawClasspath(); |
| 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 { |
| IJavaProject project = this.createJavaProject("P", new String[] {""}, ""); |
| try { |
| IPackageFragmentRoot[] oldRoots= project.getAllPackageFragmentRoots(); |
| |
| startDeltas(); |
| setClasspath(project, new IClasspathEntry[] {}); |
| IClasspathEntry[] cp= project.getRawClasspath(); |
| assertTrue("classpath should have no entries", cp.length == 0); |
| |
| // ensure the deltas are correct |
| assertTrue("there should be a delta", this.deltaListener.deltas != null && this.deltaListener.deltas.length == 1); |
| for (int i= 0; i < oldRoots.length; i++) { |
| IJavaElementDelta d= null; |
| assertTrue("root should be removed", (d= getDeltaFor(oldRoots[i])) != null && |
| (d.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0); |
| } |
| } finally { |
| stopDeltas(); |
| this.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 { |
| IJavaProject p1 = this.createJavaProject("P1", new String[] {""}, ""); |
| |
| // create container |
| JavaCore.setClasspathContainer( |
| new Path("container/default"), |
| new IJavaProject[]{ p1 }, |
| new IClasspathContainer[] { |
| new TestContainer( |
| new Path("container/default"), |
| new IClasspathEntry[] { |
| JavaCore.newLibraryEntry(new Path(getExternalJCLPath()), null, null) |
| }) |
| }, |
| null); |
| |
| // set P1's classpath with this container |
| IClasspathEntry container = JavaCore.newContainerEntry(new Path("container/default"), true); |
| p1.setRawClasspath(new IClasspathEntry[] {container}, new Path("/P1"), null); |
| |
| // create dependent project P2 |
| IJavaProject p2 = this.createJavaProject("P2", new String[] {}, new String[] {}, new String[] {"/P1"}, ""); |
| IClasspathEntry[] classpath = ((JavaProject)p2).getExpandedClasspath(true); |
| |
| // 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", getExternalJCLPath(), classpath[1].getPath().toOSString()); |
| } finally { |
| this.deleteProject("P1"); |
| this.deleteProject("P2"); |
| } |
| } |
| /** |
| * Test IJavaProject.hasClasspathCycle(IClasspathEntry[]). |
| */ |
| public void testHasClasspathCycle() throws JavaModelException, CoreException, IOException { |
| try { |
| IJavaProject p1 = this.createJavaProject("P1", new String[] {""}, ""); |
| IJavaProject p2 = this.createJavaProject("P2", new String[] {""}, ""); |
| IJavaProject p3 = this.createJavaProject("P3", new String[] {""}, new String[] {}, new String[] {"/P1"}, ""); |
| |
| IClasspathEntry[] originalP1CP= p1.getRawClasspath(); |
| IClasspathEntry[] originalP2CP= p2.getRawClasspath(); |
| |
| // Ensure no cycle reported |
| assertTrue("P1 should not have a cycle", !p1.hasClasspathCycle(originalP1CP)); |
| |
| // Ensure that adding NervousTest as a prerequesite of P2 doesn't report a cycle |
| int length = originalP2CP.length; |
| IClasspathEntry[] newCP= new IClasspathEntry[length + 1]; |
| System.arraycopy(originalP2CP, 0 , newCP, 0, length); |
| newCP[length]= JavaCore.newProjectEntry(p1.getProject().getFullPath(), false); |
| assertTrue("P2 should not have a cycle", !p2.hasClasspathCycle(newCP)); |
| p2.setRawClasspath(newCP, null); |
| |
| // Ensure that adding P3 as a prerequesite of P1 reports a cycle |
| length = originalP1CP.length; |
| newCP= new IClasspathEntry[length + 1]; |
| System.arraycopy(originalP1CP, 0 , newCP, 0, length); |
| newCP[length]= JavaCore.newProjectEntry(p2.getProject().getFullPath(), false); |
| assertTrue("P3 should have a cycle", p2.hasClasspathCycle(newCP)); |
| |
| // Ensure a cycle is not reported through markers |
| IWorkspace workspace = getJavaModel().getWorkspace(); |
| IMarker[] markers = workspace.getRoot().findMarkers(IJavaModelMarker.TRANSIENT_PROBLEM, true, 1); |
| boolean hasCycleMarker = false; |
| for (int i = 0; i < markers.length; i++){ |
| if (markers[i].getAttribute(IJavaModelMarker.CYCLE_DETECTED) != null) { |
| hasCycleMarker = true; |
| break; |
| } |
| } |
| assertTrue("Should have no cycle markers", !hasCycleMarker); |
| |
| } finally { |
| // cleanup |
| this.deleteProject("P1"); |
| this.deleteProject("P2"); |
| this.deleteProject("P3"); |
| } |
| } |
| /** |
| * Test that a marker is added when a project as a missing project in its classpath. |
| */ |
| public void testMissingPrereq1() throws CoreException { |
| try { |
| IJavaProject javaProject = this.createJavaProject("A", new String[] {}, ""); |
| IClasspathEntry[] classpath = |
| new IClasspathEntry[] { |
| JavaCore.newProjectEntry(new Path("/B")) |
| }; |
| javaProject.setRawClasspath(classpath, null); |
| this.assertMarkers( |
| "Unexpected markers", |
| "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 { |
| IJavaProject javaProject = |
| this.createJavaProject( |
| "A", |
| new String[] {}, // source folders |
| new String[] {}, // lib folders |
| new String[] {"/B"}, // projects |
| ""); |
| this.assertMarkers( |
| "Unexpected markers", |
| "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 { |
| IJavaProject 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.deleteProject("A"); |
| this.deleteProject("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 { |
| IJavaProject projectA = |
| this.createJavaProject( |
| "A", |
| new String[] {}, // source folders |
| new String[] {}, // lib folders |
| new String[] {"/B"}, // projects |
| ""); |
| IJavaProject 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 project's classpath.", |
| projectA); |
| this.assertMarkers( |
| "Unexpected markers for project B", |
| "A cycle was detected in the project's classpath.", |
| projectB); |
| |
| // delete project B |
| this.deleteProject("B"); |
| this.assertMarkers( |
| "Unexpected markers for project A after deleting of project B", |
| "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 project's classpath.", |
| projectA); |
| this.assertMarkers( |
| "Unexpected markers for project B after adding project B back", |
| "A cycle was detected in the project's classpath.", |
| projectB); |
| |
| } finally { |
| this.deleteProject("A"); |
| this.deleteProject("B"); |
| } |
| } |
| /** |
| * Setting the classpath to null should be the same as using the |
| * default classpath. |
| */ |
| public void testNullClasspath() throws CoreException { |
| try { |
| IJavaProject project = this.createJavaProject("P", new String[] {""}, ""); |
| setClasspath(project, null); |
| IClasspathEntry[] cp= project.getRawClasspath(); |
| assertTrue("classpath should have one root entry", cp.length == 1 && cp[0].getPath().equals(project.getUnderlyingResource().getFullPath())); |
| } finally { |
| this.deleteProject("P"); |
| } |
| } |
| |
| |
| public void testCycleDetection() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {""}, ""), |
| this.createJavaProject("P1", new String[] {""}, ""), |
| this.createJavaProject("P2", new String[] {""}, ""), |
| this.createJavaProject("P3", new String[] {""}, ""), |
| this.createJavaProject("P4", new String[] {""}, ""), |
| }; |
| |
| IClasspathEntry[][] extraEntries = new IClasspathEntry[][]{ |
| { JavaCore.newProjectEntry(p[1].getPath()), JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newProjectEntry(p[2].getPath()), JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newProjectEntry(p[1].getPath()) }, |
| { JavaCore.newProjectEntry(p[4].getPath())}, |
| { JavaCore.newProjectEntry(p[3].getPath()), JavaCore.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 |
| IClasspathEntry[] oldClasspath = p[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| |
| // check cycle markers |
| this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]); |
| } |
| //this.startDeltas(); |
| |
| } finally { |
| //this.stopDeltas(); |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| |
| |
| public void testCycleDetectionThroughVariables() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| String[] var = new String[]{ "v0", "v1", "v2"}; |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {""}, ""), |
| this.createJavaProject("P1", new String[] {""}, ""), |
| this.createJavaProject("P2", new String[] {""}, ""), |
| this.createJavaProject("P3", new String[] {""}, ""), |
| this.createJavaProject("P4", new String[] {""}, ""), |
| }; |
| |
| IClasspathEntry[][] extraEntries = new IClasspathEntry[][]{ |
| { JavaCore.newProjectEntry(p[1].getPath()), JavaCore.newVariableEntry(new Path(var[0]), null, null) }, |
| { JavaCore.newProjectEntry(p[2].getPath()), JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newVariableEntry(new Path(var[1]), null, null) }, |
| { JavaCore.newVariableEntry(new Path(var[2]), null, null)}, |
| { JavaCore.newProjectEntry(p[3].getPath()), JavaCore.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 |
| IClasspathEntry[] oldClasspath = p[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| |
| // update variable values |
| JavaCore.setClasspathVariables(var, variableValues[i], null); |
| |
| // check cycle markers |
| this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]); |
| } |
| //this.startDeltas(); |
| |
| } finally { |
| //this.stopDeltas(); |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| |
| public void testCycleDetectionThroughContainers() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {""}, ""), |
| this.createJavaProject("P1", new String[] {""}, ""), |
| this.createJavaProject("P2", new String[] {""}, ""), |
| this.createJavaProject("P3", new String[] {""}, ""), |
| this.createJavaProject("P4", new String[] {""}, ""), |
| }; |
| |
| IClasspathContainer[] containers = new IClasspathContainer[]{ |
| new TestContainer( |
| new Path("container0/default"), |
| new IClasspathEntry[]{ JavaCore.newProjectEntry(p[3].getPath()) }), |
| new TestContainer( |
| new Path("container1/default"), |
| new IClasspathEntry[]{ JavaCore.newProjectEntry(p[1].getPath()) }), |
| new TestContainer( |
| new Path("container2/default"), |
| new IClasspathEntry[]{ JavaCore.newProjectEntry(p[4].getPath()) }), |
| }; |
| |
| IClasspathEntry[][] extraEntries = new IClasspathEntry[][]{ |
| { JavaCore.newProjectEntry(p[1].getPath()), JavaCore.newContainerEntry(containers[0].getPath()) }, |
| { JavaCore.newProjectEntry(p[2].getPath()), JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newContainerEntry(containers[1].getPath()) }, |
| { JavaCore.newContainerEntry(containers[2].getPath())}, |
| { JavaCore.newProjectEntry(p[3].getPath()), JavaCore.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 |
| IClasspathEntry[] oldClasspath = p[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| |
| // update container paths |
| if (i == p.length - 1){ |
| JavaCore.setClasspathContainer( |
| containers[0].getPath(), |
| new IJavaProject[]{ p[0] }, |
| new IClasspathContainer[] { containers[0] }, |
| null); |
| |
| JavaCore.setClasspathContainer( |
| containers[1].getPath(), |
| new IJavaProject[]{ p[2] }, |
| new IClasspathContainer[] { containers[1] }, |
| null); |
| |
| JavaCore.setClasspathContainer( |
| containers[2].getPath(), |
| new IJavaProject[]{ p[3] }, |
| new IClasspathContainer[] { containers[2] }, |
| null); |
| } |
| |
| // check cycle markers |
| this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]); |
| } |
| //this.startDeltas(); |
| |
| } finally { |
| //this.stopDeltas(); |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| public void testCycleDetectionThroughContainerVariants() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {""}, ""), |
| this.createJavaProject("P1", new String[] {""}, ""), |
| this.createJavaProject("P2", new String[] {""}, ""), |
| this.createJavaProject("P3", new String[] {""}, ""), |
| this.createJavaProject("P4", new String[] {""}, ""), |
| }; |
| |
| class TestContainer implements IClasspathContainer { |
| IPath path; |
| IClasspathEntry[] entries; |
| TestContainer(IPath path, IClasspathEntry[] entries){ |
| this.path = path; |
| this.entries = entries; |
| } |
| public IPath getPath() { return this.path; } |
| public IClasspathEntry[] getClasspathEntries() { return this.entries; } |
| public String getDescription() { return null; } |
| public int getKind() { return 0; } |
| }; |
| |
| IClasspathContainer[] containers = new IClasspathContainer[]{ |
| new TestContainer( |
| new Path("container0/default"), |
| new IClasspathEntry[]{ JavaCore.newProjectEntry(p[3].getPath()) }), |
| new TestContainer( |
| new Path("container0/default"), |
| new IClasspathEntry[]{ JavaCore.newProjectEntry(p[1].getPath()) }), |
| new TestContainer( |
| new Path("container0/default"), |
| new IClasspathEntry[]{ JavaCore.newProjectEntry(p[4].getPath()) }), |
| }; |
| |
| IClasspathEntry[][] extraEntries = new IClasspathEntry[][]{ |
| { JavaCore.newProjectEntry(p[1].getPath()), JavaCore.newContainerEntry(containers[0].getPath()) }, |
| { JavaCore.newProjectEntry(p[2].getPath()), JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newContainerEntry(containers[1].getPath()) }, |
| { JavaCore.newContainerEntry(containers[2].getPath())}, |
| { JavaCore.newProjectEntry(p[3].getPath()), JavaCore.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 |
| IClasspathEntry[] oldClasspath = p[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| |
| // update same container path for multiple projects |
| if (i == p.length - 1){ |
| JavaCore.setClasspathContainer( |
| containers[0].getPath(), |
| new IJavaProject[]{ p[0], p[2], p[3] }, |
| new IClasspathContainer[] { containers[0], containers[1], containers[2] }, |
| null); |
| } |
| |
| // check cycle markers |
| this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]); |
| } |
| //this.startDeltas(); |
| |
| } finally { |
| //this.stopDeltas(); |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| public void testCycleDetection2() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {""}, ""), |
| this.createJavaProject("P1", new String[] {""}, ""), |
| this.createJavaProject("P2", new String[] {""}, ""), |
| this.createJavaProject("P3", new String[] {""}, ""), |
| this.createJavaProject("P4", new String[] {""}, ""), |
| }; |
| |
| IClasspathEntry[][] extraEntries = new IClasspathEntry[][]{ |
| { JavaCore.newProjectEntry(p[1].getPath()), JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newProjectEntry(p[2].getPath()) }, |
| { JavaCore.newProjectEntry(p[0].getPath()) }, |
| { JavaCore.newProjectEntry(p[4].getPath())}, |
| { JavaCore.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 |
| IClasspathEntry[] oldClasspath = p[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| |
| // check cycle markers |
| this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]); |
| } |
| //this.startDeltas(); |
| |
| } finally { |
| //this.stopDeltas(); |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| |
| public void testCycleDetection3() throws CoreException { |
| |
| IJavaProject[] p = null; |
| try { |
| |
| p = new IJavaProject[]{ |
| this.createJavaProject("P0", new String[] {""}, ""), |
| this.createJavaProject("P1", new String[] {""}, ""), |
| this.createJavaProject("P2", new String[] {""}, ""), |
| this.createJavaProject("P3", new String[] {""}, ""), |
| this.createJavaProject("P4", new String[] {""}, ""), |
| this.createJavaProject("P5", new String[] {""}, ""), |
| }; |
| |
| IClasspathEntry[][] extraEntries = new IClasspathEntry[][]{ |
| { JavaCore.newProjectEntry(p[2].getPath()), JavaCore.newProjectEntry(p[4].getPath()) }, |
| { JavaCore.newProjectEntry(p[0].getPath()) }, |
| { JavaCore.newProjectEntry(p[3].getPath()) }, |
| { JavaCore.newProjectEntry(p[1].getPath())}, |
| { JavaCore.newProjectEntry(p[5].getPath()) }, |
| { JavaCore.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 |
| IClasspathEntry[] oldClasspath = p[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| |
| // check cycle markers |
| this.assertCycleMarkers(p[i], p, expectedCycleParticipants[i]); |
| } |
| //this.startDeltas(); |
| |
| } finally { |
| //this.stopDeltas(); |
| if (p != null){ |
| for (int i = 0; i < p.length; i++){ |
| this.deleteProject(p[i].getElementName()); |
| } |
| } |
| } |
| } |
| public void testDenseCycleDetection() throws CoreException { |
| denseCycleDetection(5); |
| denseCycleDetection(10); |
| denseCycleDetection(20); |
| //denseCycleDetection(100); |
| } |
| |
| private void denseCycleDetection(int numberOfParticipants) throws CoreException { |
| |
| long start = System.currentTimeMillis(); |
| IJavaProject[] projects = new IJavaProject[numberOfParticipants]; |
| int[] allProjectsInCycle = new int[numberOfParticipants]; |
| try { |
| for (int i = 0; i < numberOfParticipants; i++){ |
| projects[i] = this.createJavaProject("P"+i, new String[]{""}, ""); |
| allProjectsInCycle[i] = 1; |
| } |
| for (int i = 0; i < numberOfParticipants; i++){ |
| IClasspathEntry[] extraEntries = new IClasspathEntry[numberOfParticipants-1]; |
| int index = 0; |
| for (int j = 0; j < numberOfParticipants; j++){ |
| if (i == j) continue; |
| extraEntries[index++] = JavaCore.newProjectEntry(projects[j].getPath()); |
| } |
| // append project references |
| IClasspathEntry[] oldClasspath = projects[i].getRawClasspath(); |
| IClasspathEntry[] newClasspath = new IClasspathEntry[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].setRawClasspath(newClasspath, null); |
| }; |
| |
| System.out.println("Dense cycle check ("+numberOfParticipants+" participants) : "+ (System.currentTimeMillis()-start)+" ms"); |
| for (int i = 0; i < numberOfParticipants; i++){ |
| // check cycle markers |
| this.assertCycleMarkers(projects[i], projects, allProjectsInCycle); |
| } |
| |
| } finally { |
| if (projects != null){ |
| for (int i = 0; i < numberOfParticipants; i++){ |
| if (projects[i] != null) |
| this.deleteProject(projects[i].getElementName()); |
| } |
| } |
| } |
| } |
| |
| } |