### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.builder Index: src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java,v retrieving revision 1.44 diff -u -r1.44 TestingEnvironment.java --- src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java 29 Mar 2006 03:16:23 -0000 1.44 +++ src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java 13 Oct 2006 15:53:52 -0000 @@ -21,6 +21,8 @@ import org.eclipse.jdt.internal.core.JavaProject; import java.io.*; import java.util.*; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; public class TestingEnvironment { @@ -109,6 +111,10 @@ return addClass(packageFragmentRootPath, className, contents); } +public void addClassFolder(IPath projectPath, IPath classFolderPath) throws JavaModelException { + addEntry(projectPath, JavaCore.newLibraryEntry(classFolderPath, null, null)); +} + /** Adds a package to the given package fragment root * in the workspace. The package fragment root is created * if necessary. If a package with the same name already @@ -288,6 +294,42 @@ return path; } +public IPath addInternalJar(IPath projectPath, String zipName, + String[] entryNames, String [] fileNames, boolean isExported) + throws JavaModelException { + try { + checkAssertion("entryNames must not be null", entryNames != null); + checkAssertion("fileNames must not be null", fileNames != null); + int entriesNb = entryNames.length; + checkAssertion("entryNames and fileNames must have the same length", + entriesNb == fileNames.length); + ByteArrayOutputStream sinkArray = new ByteArrayOutputStream(); + BufferedOutputStream outputBuffer = new BufferedOutputStream(sinkArray); + BufferedInputStream inputBuffer; + IProject project = getProject(projectPath); + JarOutputStream jar = new JarOutputStream(outputBuffer); + byte[] bytes = new byte[1024]; + for (int i = 0; i < entriesNb; i++) { + ZipEntry classFile = new ZipEntry(entryNames[i]); + jar.putNextEntry(classFile); + inputBuffer = new BufferedInputStream( + project.getFile(fileNames[i]).getContents()); + int bytesNb; + while ((bytesNb = inputBuffer.read(bytes)) != -1) { + jar.write(bytes, 0, bytesNb); + } + inputBuffer.close(); + } + jar.close(); + outputBuffer.close(); + return addInternalJar(projectPath, zipName, sinkArray.toByteArray()); + } catch (Exception e) { + e.printStackTrace(); + checkAssertion("could not create jar file", false); + return null; // won't get here + } +} + private void checkAssertion(String message, boolean b) { Assert.isTrue(b, message); } Index: src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java,v retrieving revision 1.41 diff -u -r1.41 MultiProjectTests.java --- src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java 6 Apr 2006 19:16:04 -0000 1.41 +++ src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java 13 Oct 2006 15:53:52 -0000 @@ -14,8 +14,17 @@ import junit.framework.Test; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IWorkspaceDescription; +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -780,6 +789,178 @@ } } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=114349 +// this one fails; compare with testCycle7 (only one change in Object source), +// which passes + public void testCycle6() throws JavaModelException { + Hashtable options = JavaCore.getOptions(); + Hashtable newOptions = JavaCore.getOptions(); + newOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING); + + JavaCore.setOptions(newOptions); + + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("P1"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); + IPath root1 = env.addPackageFragmentRoot(p1, "src"); + env.setOutputFolder(p1, "bin"); + + env.addClass(root1, "java/lang", "Object", + "package java.lang;\n" + + "public class Object {\n" + + " Class getClass() { return null; }\n" + + " String toString() { return \"\"; }\n" + // the line that changes + "}\n" + ); + + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("P2"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); + IPath root2 = env.addPackageFragmentRoot(p2, "src"); + env.setOutputFolder(p2, "bin"); + + env.addClass(root2, "java/lang", "Class", + "package java.lang;\n" + + "public class Class {\n" + + " String getName() { return \"\"; };\n" + + "}\n" + ); + + //---------------------------- + // Project3 + //---------------------------- + IPath p3 = env.addProject("P3"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p3, ""); + IPath root3 = env.addPackageFragmentRoot(p3, "src"); + env.setOutputFolder(p3, "bin"); + + env.addClass(root3, "java/lang", "String", + "package java.lang;\n" + + "public class String {\n" + + "}\n" + ); + + // Dependencies + IPath[] accessiblePaths = new IPath[] {new Path("java/lang/*")}; + IPath[] forbiddenPaths = new IPath[] {new Path("**/*")}; + env.addRequiredProject(p1, p2, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p1, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p2, accessiblePaths, forbiddenPaths, false); + + try { + fullBuild(); + + expectingOnlySpecificProblemsFor(p1,new Problem[]{ + new Problem("p1", "A cycle was detected in the build path of project: P1", p1, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p2,new Problem[]{ + new Problem("p2", "A cycle was detected in the build path of project: P2", p2, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p3,new Problem[]{ + new Problem("p3", "A cycle was detected in the build path of project: P3", p3, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + + } finally { + JavaCore.setOptions(options); + } + } + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=114349 +// this one passes; compare with testCycle6 (only one change in Object source), +// which fails + public void testCycle7() throws JavaModelException { + Hashtable options = JavaCore.getOptions(); + Hashtable newOptions = JavaCore.getOptions(); + newOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING); + + JavaCore.setOptions(newOptions); + + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("P1"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); + IPath root1 = env.addPackageFragmentRoot(p1, "src"); + env.setOutputFolder(p1, "bin"); + + env.addClass(root1, "java/lang", "Object", + "package java.lang;\n" + + "public class Object {\n" + + " Class getClass() { return null; }\n" + + " String toString() { return null; }\n" + // the line that changes + "}\n" + ); + + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("P2"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); + IPath root2 = env.addPackageFragmentRoot(p2, "src"); + env.setOutputFolder(p2, "bin"); + + env.addClass(root2, "java/lang", "Class", + "package java.lang;\n" + + "public class Class {\n" + + " String getName() { return \"\"; };\n" + + "}\n" + ); + + //---------------------------- + // Project3 + //---------------------------- + IPath p3 = env.addProject("P3"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p3, ""); + IPath root3 = env.addPackageFragmentRoot(p3, "src"); + env.setOutputFolder(p3, "bin"); + + env.addClass(root3, "java/lang", "String", + "package java.lang;\n" + + "public class String {\n" + + "}\n" + ); + + // Dependencies + IPath[] accessiblePaths = new IPath[] {new Path("java/lang/*")}; + IPath[] forbiddenPaths = new IPath[] {new Path("**/*")}; + env.addRequiredProject(p1, p2, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p1, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p2, p3, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p1, accessiblePaths, forbiddenPaths, false); + env.addRequiredProject(p3, p2, accessiblePaths, forbiddenPaths, false); + + try { + fullBuild(); + + expectingOnlySpecificProblemsFor(p1,new Problem[]{ + new Problem("p1", "A cycle was detected in the build path of project: P1", p1, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p2,new Problem[]{ + new Problem("p2", "A cycle was detected in the build path of project: P2", p2, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + expectingOnlySpecificProblemsFor(p3,new Problem[]{ + new Problem("p3", "A cycle was detected in the build path of project: P3", p3, -1, -1, CategorizedProblem.CAT_BUILDPATH)//$NON-NLS-1$ //$NON-NLS-2$ + }); + + } finally { + JavaCore.setOptions(options); + } + } + /* * Full buid case */ @@ -1223,5 +1404,262 @@ env.setBuildOrder(null); } } - +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=160550 +public void _test0100_cycle_with_bad_library() throws CoreException { + Hashtable options = JavaCore.getOptions(); + Hashtable newOptions = JavaCore.getOptions(); + newOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING); + JavaCore.setOptions(newOptions); + try { + // jar preparation (broken jar: l/Super.class missing) + IPath brokenLibProjectPath = env.addProject("Lib"); + env.addExternalJars(brokenLibProjectPath, Util.getJavaClassLibs()); + IProject brokenLibProject = env.getProject(brokenLibProjectPath); + env.removePackageFragmentRoot(brokenLibProjectPath, ""); + IPath root0 = env.addPackageFragmentRoot(brokenLibProjectPath, "src"); + env.setOutputFolder(brokenLibProjectPath, "bin"); + env.addClass(root0, "l", "Super", + "package l;\n" + + "public class Super {\n" + + "}\n" + ); + env.addClass(root0, "l", "Sub", + "package l;\n" + + "public class Sub extends Super {\n" + + "}\n" + ); + fullBuild(); + String brokenLibJarExternalPath = + env.addInternalJar(brokenLibProjectPath, "broken.jar", + new String[] {"l/Sub.class"}, new String[]{"bin/l/Sub.class"}, + // avoid to include Super on purpose + false).toString(); + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("P1"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); + IPath root1 = env.addPackageFragmentRoot(p1, "src"); + env.setOutputFolder(p1, "bin"); + env.addExternalJars(p1, Util.getJavaClassLibs()); + env.addExternalJar(p1, brokenLibJarExternalPath); + /* IPath xPath = */ env.addClass(root1, "p", "X", + "package p;\n" + + "public class X extends l.Sub {\n" + + " q.Y m;\n" + + "}\n" + ); + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("P2"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); + IPath root2 = env.addPackageFragmentRoot(p2, "src"); + env.setOutputFolder(p2, "bin"); + env.addExternalJars(p2, Util.getJavaClassLibs()); + env.addExternalJar(p2, brokenLibJarExternalPath); + /* IPath yPath = */ env.addClass(root2, "q", "Y", + "package q;\n" + + "public class Y extends l.Sub {\n" + + " p.X m;\n" + + "}\n" + ); + // Dependencies + env.addRequiredProject(p1, p2, null, null, false); + env.addRequiredProject(p2, p1, null, null, false); + // Re-launcher + class PostBuildJob extends WorkspaceJob implements IResourceChangeListener { + int invocationsNb = 0; + public PostBuildJob() { + super("Post build"); + } + public void resourceChanged(IResourceChangeEvent event) { + invocationsNb++; + if (DEBUG) { + System.out.println("event #" + invocationsNb); + } + schedule(100); + } + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + try { + Thread.sleep(500); + } catch (InterruptedException e) { /* */ } + return Status.OK_STATUS; + } + } + PostBuildJob listener = new PostBuildJob(); + try { + fullBuild(); +// TODO the problems layout is changed by patches, hence they are deactivated for now +// expectingOnlySpecificProblemsFor(p1, new Problem[] { +// new Problem("p1", "A cycle was detected in the build path of project: P1", +// p1, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p1", "The project was not built since its build path is incomplete. Cannot find the class file for l.Super. Fix the build path then try building this project", +// p1, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p1", "The type l.Super cannot be resolved. It is indirectly referenced from required .class files", +// xPath, 34, 39, CategorizedProblem.CAT_BUILDPATH), +// }); +// expectingOnlySpecificProblemsFor(p2, new Problem[] { +// new Problem("p2", "A cycle was detected in the build path of project: P2", +// p2, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p2", "The project was not built since its build path is incomplete. Cannot find the class file for l.Super. Fix the build path then try building this project", +// p2, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p2", "The type l.Super cannot be resolved. It is indirectly referenced from required .class files", +// yPath, 34, 39, CategorizedProblem.CAT_BUILDPATH), +// }); + IWorkspaceDescription description = brokenLibProject.getWorkspace().getDescription(); + description.setAutoBuilding(true); + brokenLibProject.getWorkspace().setDescription(description); + brokenLibProject.getWorkspace(). + addResourceChangeListener(listener, IResourceChangeEvent.POST_BUILD); + env.addClass(root1, "p", "X", + "package p;\n" + + "public class X extends l.Sub {\n" + + " q.Y m;\n" + + "}\n" + ); + try { + Thread.sleep(3000); // beware, too low a delay would miss the point + } catch (InterruptedException e) { /* */ } + if (listener.invocationsNb > 1) { + fail("looping in build (" + listener.invocationsNb + " invocations)"); + } + } finally { + brokenLibProject.getWorkspace().removeResourceChangeListener(listener); + brokenLibProject.getWorkspace().getDescription().setAutoBuilding(false); + } + } finally { + JavaCore.setOptions(options); + } +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=160550 +public void _test0101_cycle_with_bad_class_folder() throws CoreException { + Hashtable options = JavaCore.getOptions(); + Hashtable newOptions = JavaCore.getOptions(); + newOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING); + JavaCore.setOptions(newOptions); + try { + // jar preparation (broken jar: l/Super.class missing) + IPath brokenLibProjectPath = env.addProject("Lib"); + env.addExternalJars(brokenLibProjectPath, Util.getJavaClassLibs()); + IProject brokenLibProject = env.getProject(brokenLibProjectPath); + env.removePackageFragmentRoot(brokenLibProjectPath, ""); + IPath root0 = env.addPackageFragmentRoot(brokenLibProjectPath, + "src1", null, false, "bin1"); + env.addClass(root0, "l", "Super", + "package l;\n" + + "public class Super {\n" + + "}\n" + ); + root0 = env.addPackageFragmentRoot(brokenLibProjectPath, + "src2", null, false, "bin2"); + env.addClass(root0, "l", "Sub", + "package l;\n" + + "public class Sub extends Super {\n" + + "}\n" + ); + fullBuild(); + IPath brokenClassFolderPath = brokenLibProjectPath.append("bin2"); + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("P1"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); + IPath root1 = env.addPackageFragmentRoot(p1, "src"); + env.setOutputFolder(p1, "bin"); + env.addExternalJars(p1, Util.getJavaClassLibs()); + env.addClassFolder(p1, brokenClassFolderPath); + /* IPath xPath = */ env.addClass(root1, "p", "X", + "package p;\n" + + "public class X extends l.Sub {\n" + + " q.Y m;\n" + + "}\n" + ); + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("P2"); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); + IPath root2 = env.addPackageFragmentRoot(p2, "src"); + env.setOutputFolder(p2, "bin"); + env.addExternalJars(p2, Util.getJavaClassLibs()); + env.addClassFolder(p2, brokenClassFolderPath); + /* IPath yPath = */ env.addClass(root2, "q", "Y", + "package q;\n" + + "public class Y extends l.Sub {\n" + + " p.X m;\n" + + "}\n" + ); + // Dependencies + env.addRequiredProject(p1, p2, null, null, false); + env.addRequiredProject(p2, p1, null, null, false); + // Re-launcher + class PostBuildJob extends WorkspaceJob implements IResourceChangeListener { + int invocationsNb = 0; + public PostBuildJob() { + super("Post build"); + } + public void resourceChanged(IResourceChangeEvent event) { + invocationsNb++; + if (DEBUG) { + System.out.println("event #" + invocationsNb); + } + schedule(100); + } + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + try { + Thread.sleep(500); + } catch (InterruptedException e) { /* */ } + return Status.OK_STATUS; + } + } + PostBuildJob listener = new PostBuildJob(); + try { + fullBuild(); +// TODO the problems layout is changed by patches, hence they are deactivated for now +// expectingOnlySpecificProblemsFor(p1, new Problem[] { +// new Problem("p1", "A cycle was detected in the build path of project: P1", +// p1, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p1", "The project was not built since its build path is incomplete. Cannot find the class file for l.Super. Fix the build path then try building this project", +// p1, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p1", "The type l.Super cannot be resolved. It is indirectly referenced from required .class files", +// xPath, 34, 39, CategorizedProblem.CAT_BUILDPATH), +// }); +// expectingOnlySpecificProblemsFor(p2, new Problem[] { +// new Problem("p2", "A cycle was detected in the build path of project: P2", +// p2, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p2", "The project was not built since its build path is incomplete. Cannot find the class file for l.Super. Fix the build path then try building this project", +// p2, -1, -1, CategorizedProblem.CAT_BUILDPATH), +// new Problem("p2", "The type l.Super cannot be resolved. It is indirectly referenced from required .class files", +// yPath, 34, 39, CategorizedProblem.CAT_BUILDPATH), +// }); + IWorkspaceDescription description = brokenLibProject.getWorkspace().getDescription(); + description.setAutoBuilding(true); + brokenLibProject.getWorkspace().setDescription(description); + brokenLibProject.getWorkspace(). + addResourceChangeListener(listener, IResourceChangeEvent.POST_BUILD); + env.addClass(root1, "p", "X", + "package p;\n" + + "public class X extends l.Sub {\n" + + " q.Y m;\n" + + "}\n" + ); + try { + Thread.sleep(3000); // beware, too low a delay would miss the point + } catch (InterruptedException e) { /* */ } + if (listener.invocationsNb > 1) { + fail("looping in build (" + listener.invocationsNb + " invocations)"); + } + } finally { + brokenLibProject.getWorkspace().removeResourceChangeListener(listener); + brokenLibProject.getWorkspace().getDescription().setAutoBuilding(false); + } + } finally { + JavaCore.setOptions(options); + } +} }