different times since they have a mutual dependency. I have introduced a 100 millisecond tolerance to catch this situation PR: 7529 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272303 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -4,13 +4,15 @@ | |||
| <property name="src1.dir" value="src1"/> | |||
| <property name="src2.dir" value="src2"/> | |||
| <property name="src3.dir" value="src3"/> | |||
| <property name="src4.dir" value="src4"/> | |||
| <property name="tempsrc.dir" value="working"/> | |||
| <property name="classes.dir" value="classes"/> | |||
| <target name="help"> | |||
| <echo>This buildfile is used as part of Ant's test suite.</echo> | |||
| </target> | |||
| <target name="basesetup"> | |||
| <target name="basesetup" depends="clean"> | |||
| <mkdir dir="${tempsrc.dir}"/> | |||
| </target> | |||
| @@ -32,6 +34,12 @@ | |||
| </copy> | |||
| </target> | |||
| <target name="src4setup" depends="basesetup"> | |||
| <copy todir="${tempsrc.dir}"> | |||
| <fileset dir="${src4.dir}"/> | |||
| </copy> | |||
| </target> | |||
| <target name="compile"> | |||
| <mkdir dir="${classes.dir}"/> | |||
| <javac srcdir="${tempsrc.dir}" destdir="${classes.dir}"/> | |||
| @@ -96,4 +104,29 @@ | |||
| <depend srcdir="${tempsrc.dir}" destdir="${classes.dir}" closure="yes"/> | |||
| <fileset id="result" dir="${classes.dir}"/> | |||
| </target> | |||
| <target name="testnosource" depends="src1setup, compile"> | |||
| <depend destdir="${classes.dir}" closure="yes"/> | |||
| </target> | |||
| <target name="testemptysource" depends="src1setup, compile"> | |||
| <depend srcdir="" destdir="${classes.dir}" closure="yes"/> | |||
| </target> | |||
| <target name="testinnerclosure" depends="src4setup"> | |||
| <mkdir dir="${classes.dir}"/> | |||
| <path id="path.compile"> | |||
| <pathelement location="${classes.dir}"/> | |||
| </path> | |||
| <javac srcdir="${tempsrc.dir}" destdir="${classes.dir}" | |||
| classpathref="path.compile"/> | |||
| <sleep seconds="3"/> | |||
| <depend srcdir="${tempsrc.dir}" destdir="${classes.dir}" | |||
| closure="yes" dump="yes" | |||
| classpathref="path.compile"/> | |||
| <fileset id="result" dir="${classes.dir}"/> | |||
| </target> | |||
| </project> | |||
| @@ -0,0 +1,7 @@ | |||
| package test; | |||
| public class Outer { | |||
| static class Inner { | |||
| } | |||
| } | |||
| @@ -79,6 +79,11 @@ import org.apache.tools.ant.types.Reference; | |||
| * @author Conor MacNeill | |||
| */ | |||
| public class Depend extends MatchingTask { | |||
| /** Tolerance on time checks to take into account inner to outer class dependencies when | |||
| * the classes are written at slightly different times | |||
| */ | |||
| static private final int TIME_TOLERANCE = 100; | |||
| /** | |||
| * A class (struct) user to manage information about a class | |||
| * | |||
| @@ -484,9 +489,14 @@ public class Depend extends MatchingTask { | |||
| public void execute() throws BuildException { | |||
| try { | |||
| long start = System.currentTimeMillis(); | |||
| if (srcPath == null) { | |||
| throw new BuildException("srcdir attribute must be set", | |||
| location); | |||
| } | |||
| String[] srcPathList = srcPath.list(); | |||
| if (srcPathList.length == 0) { | |||
| throw new BuildException("srcdir attribute must be set!", | |||
| throw new BuildException("srcdir attribute must be non-empty", | |||
| location); | |||
| } | |||
| @@ -559,7 +569,8 @@ public class Depend extends MatchingTask { | |||
| Hashtable dependencies = (Hashtable)classpathDependencies.get(className); | |||
| for (Enumeration e2 = dependencies.elements(); e2.hasMoreElements(); ) { | |||
| File classpathFile = (File)e2.nextElement(); | |||
| if (classpathFile.lastModified() > info.absoluteFile.lastModified()) { | |||
| if (classpathFile.lastModified() | |||
| > (info.absoluteFile.lastModified() + TIME_TOLERANCE)) { | |||
| log("Class " + className + | |||
| " is out of date with respect to " + classpathFile, Project.MSG_DEBUG); | |||
| outOfDateClasses.put(className, className); | |||
| @@ -607,7 +618,8 @@ public class Depend extends MatchingTask { | |||
| // there was no class file. add this class to the list | |||
| outOfDateClasses.put(className, className); | |||
| } else { | |||
| if (srcFile.lastModified() > info.absoluteFile.lastModified()) { | |||
| if (srcFile.lastModified() | |||
| > (info.absoluteFile.lastModified() + TIME_TOLERANCE)) { | |||
| outOfDateClasses.put(className, className); | |||
| } | |||
| } | |||
| @@ -92,13 +92,7 @@ public class DependTest extends BuildFileTest { | |||
| public void testDirect() { | |||
| Project project = getProject(); | |||
| executeTarget("testdirect"); | |||
| FileSet resultFileSet = (FileSet)project.getReference(RESULT_FILESET); | |||
| DirectoryScanner scanner = resultFileSet.getDirectoryScanner(project); | |||
| String[] scannedFiles = scanner.getIncludedFiles(); | |||
| Hashtable files = new Hashtable(); | |||
| for (int i = 0; i < scannedFiles.length; ++i) { | |||
| files.put(scannedFiles[i], scannedFiles[i]); | |||
| } | |||
| Hashtable files = getResultFiles(); | |||
| assertEquals("Depend did not leave correct number of files", 2, | |||
| files.size()); | |||
| assertTrue("Result did not contain A.class", | |||
| @@ -113,13 +107,7 @@ public class DependTest extends BuildFileTest { | |||
| public void testClosure() { | |||
| Project project = getProject(); | |||
| executeTarget("testclosure"); | |||
| FileSet resultFileSet = (FileSet)project.getReference(RESULT_FILESET); | |||
| DirectoryScanner scanner = resultFileSet.getDirectoryScanner(project); | |||
| String[] scannedFiles = scanner.getIncludedFiles(); | |||
| Hashtable files = new Hashtable(); | |||
| for (int i = 0; i < scannedFiles.length; ++i) { | |||
| files.put(scannedFiles[i], scannedFiles[i]); | |||
| } | |||
| Hashtable files = getResultFiles(); | |||
| assertEquals("Depend did not leave correct number of files", 1, | |||
| files.size()); | |||
| assertTrue("Result did not contain D.class", | |||
| @@ -132,15 +120,8 @@ public class DependTest extends BuildFileTest { | |||
| public void testInner() { | |||
| Project project = getProject(); | |||
| executeTarget("testinner"); | |||
| FileSet resultFileSet = (FileSet)project.getReference(RESULT_FILESET); | |||
| DirectoryScanner scanner = resultFileSet.getDirectoryScanner(project); | |||
| String[] scannedFiles = scanner.getIncludedFiles(); | |||
| Hashtable files = new Hashtable(); | |||
| for (int i = 0; i < scannedFiles.length; ++i) { | |||
| files.put(scannedFiles[i], scannedFiles[i]); | |||
| } | |||
| assertEquals("Depend did not leave correct number of files", 0, | |||
| files.size()); | |||
| getResultFiles().size()); | |||
| } | |||
| /** | |||
| @@ -150,6 +131,27 @@ public class DependTest extends BuildFileTest { | |||
| public void testInnerInner() { | |||
| Project project = getProject(); | |||
| executeTarget("testinnerinner"); | |||
| assertEquals("Depend did not leave correct number of files", 0, | |||
| getResultFiles().size()); | |||
| } | |||
| /** | |||
| * Test that an exception is thrown when there is no source | |||
| */ | |||
| public void testNoSource() { | |||
| expectBuildExceptionContaining("testnosource", | |||
| "No source specified", "srcdir attribute must be set"); | |||
| } | |||
| /** | |||
| * Test that an exception is thrown when the source attribute is empty | |||
| */ | |||
| public void testEmptySource() { | |||
| expectBuildExceptionContaining("testemptysource", | |||
| "No source specified", "srcdir attribute must be non-empty"); | |||
| } | |||
| private Hashtable getResultFiles() { | |||
| FileSet resultFileSet = (FileSet)project.getReference(RESULT_FILESET); | |||
| DirectoryScanner scanner = resultFileSet.getDirectoryScanner(project); | |||
| String[] scannedFiles = scanner.getIncludedFiles(); | |||
| @@ -157,7 +159,18 @@ public class DependTest extends BuildFileTest { | |||
| for (int i = 0; i < scannedFiles.length; ++i) { | |||
| files.put(scannedFiles[i], scannedFiles[i]); | |||
| } | |||
| assertEquals("Depend did not leave correct number of files", 0, | |||
| files.size()); | |||
| return files; | |||
| } | |||
| /** | |||
| * Test mutual dependency between inner and outer do not cause both to be | |||
| * deleted | |||
| */ | |||
| public void testInnerClosure() { | |||
| Project project = getProject(); | |||
| executeTarget("testinnerclosure"); | |||
| assertEquals("Depend did not leave correct number of files", 2, | |||
| getResultFiles().size()); | |||
| } | |||
| } | |||