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="src1.dir" value="src1"/> | ||||
| <property name="src2.dir" value="src2"/> | <property name="src2.dir" value="src2"/> | ||||
| <property name="src3.dir" value="src3"/> | <property name="src3.dir" value="src3"/> | ||||
| <property name="src4.dir" value="src4"/> | |||||
| <property name="tempsrc.dir" value="working"/> | <property name="tempsrc.dir" value="working"/> | ||||
| <property name="classes.dir" value="classes"/> | <property name="classes.dir" value="classes"/> | ||||
| <target name="help"> | <target name="help"> | ||||
| <echo>This buildfile is used as part of Ant's test suite.</echo> | <echo>This buildfile is used as part of Ant's test suite.</echo> | ||||
| </target> | </target> | ||||
| <target name="basesetup"> | |||||
| <target name="basesetup" depends="clean"> | |||||
| <mkdir dir="${tempsrc.dir}"/> | <mkdir dir="${tempsrc.dir}"/> | ||||
| </target> | </target> | ||||
| @@ -32,6 +34,12 @@ | |||||
| </copy> | </copy> | ||||
| </target> | </target> | ||||
| <target name="src4setup" depends="basesetup"> | |||||
| <copy todir="${tempsrc.dir}"> | |||||
| <fileset dir="${src4.dir}"/> | |||||
| </copy> | |||||
| </target> | |||||
| <target name="compile"> | <target name="compile"> | ||||
| <mkdir dir="${classes.dir}"/> | <mkdir dir="${classes.dir}"/> | ||||
| <javac srcdir="${tempsrc.dir}" destdir="${classes.dir}"/> | <javac srcdir="${tempsrc.dir}" destdir="${classes.dir}"/> | ||||
| @@ -96,4 +104,29 @@ | |||||
| <depend srcdir="${tempsrc.dir}" destdir="${classes.dir}" closure="yes"/> | <depend srcdir="${tempsrc.dir}" destdir="${classes.dir}" closure="yes"/> | ||||
| <fileset id="result" dir="${classes.dir}"/> | <fileset id="result" dir="${classes.dir}"/> | ||||
| </target> | </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> | </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 | * @author Conor MacNeill | ||||
| */ | */ | ||||
| public class Depend extends MatchingTask { | 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 | * A class (struct) user to manage information about a class | ||||
| * | * | ||||
| @@ -484,9 +489,14 @@ public class Depend extends MatchingTask { | |||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| try { | try { | ||||
| long start = System.currentTimeMillis(); | long start = System.currentTimeMillis(); | ||||
| if (srcPath == null) { | |||||
| throw new BuildException("srcdir attribute must be set", | |||||
| location); | |||||
| } | |||||
| String[] srcPathList = srcPath.list(); | String[] srcPathList = srcPath.list(); | ||||
| if (srcPathList.length == 0) { | if (srcPathList.length == 0) { | ||||
| throw new BuildException("srcdir attribute must be set!", | |||||
| throw new BuildException("srcdir attribute must be non-empty", | |||||
| location); | location); | ||||
| } | } | ||||
| @@ -559,7 +569,8 @@ public class Depend extends MatchingTask { | |||||
| Hashtable dependencies = (Hashtable)classpathDependencies.get(className); | Hashtable dependencies = (Hashtable)classpathDependencies.get(className); | ||||
| for (Enumeration e2 = dependencies.elements(); e2.hasMoreElements(); ) { | for (Enumeration e2 = dependencies.elements(); e2.hasMoreElements(); ) { | ||||
| File classpathFile = (File)e2.nextElement(); | File classpathFile = (File)e2.nextElement(); | ||||
| if (classpathFile.lastModified() > info.absoluteFile.lastModified()) { | |||||
| if (classpathFile.lastModified() | |||||
| > (info.absoluteFile.lastModified() + TIME_TOLERANCE)) { | |||||
| log("Class " + className + | log("Class " + className + | ||||
| " is out of date with respect to " + classpathFile, Project.MSG_DEBUG); | " is out of date with respect to " + classpathFile, Project.MSG_DEBUG); | ||||
| outOfDateClasses.put(className, className); | outOfDateClasses.put(className, className); | ||||
| @@ -607,7 +618,8 @@ public class Depend extends MatchingTask { | |||||
| // there was no class file. add this class to the list | // there was no class file. add this class to the list | ||||
| outOfDateClasses.put(className, className); | outOfDateClasses.put(className, className); | ||||
| } else { | } else { | ||||
| if (srcFile.lastModified() > info.absoluteFile.lastModified()) { | |||||
| if (srcFile.lastModified() | |||||
| > (info.absoluteFile.lastModified() + TIME_TOLERANCE)) { | |||||
| outOfDateClasses.put(className, className); | outOfDateClasses.put(className, className); | ||||
| } | } | ||||
| } | } | ||||
| @@ -92,13 +92,7 @@ public class DependTest extends BuildFileTest { | |||||
| public void testDirect() { | public void testDirect() { | ||||
| Project project = getProject(); | Project project = getProject(); | ||||
| executeTarget("testdirect"); | 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, | assertEquals("Depend did not leave correct number of files", 2, | ||||
| files.size()); | files.size()); | ||||
| assertTrue("Result did not contain A.class", | assertTrue("Result did not contain A.class", | ||||
| @@ -113,13 +107,7 @@ public class DependTest extends BuildFileTest { | |||||
| public void testClosure() { | public void testClosure() { | ||||
| Project project = getProject(); | Project project = getProject(); | ||||
| executeTarget("testclosure"); | 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, | assertEquals("Depend did not leave correct number of files", 1, | ||||
| files.size()); | files.size()); | ||||
| assertTrue("Result did not contain D.class", | assertTrue("Result did not contain D.class", | ||||
| @@ -132,15 +120,8 @@ public class DependTest extends BuildFileTest { | |||||
| public void testInner() { | public void testInner() { | ||||
| Project project = getProject(); | Project project = getProject(); | ||||
| executeTarget("testinner"); | 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, | 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() { | public void testInnerInner() { | ||||
| Project project = getProject(); | Project project = getProject(); | ||||
| executeTarget("testinnerinner"); | 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); | FileSet resultFileSet = (FileSet)project.getReference(RESULT_FILESET); | ||||
| DirectoryScanner scanner = resultFileSet.getDirectoryScanner(project); | DirectoryScanner scanner = resultFileSet.getDirectoryScanner(project); | ||||
| String[] scannedFiles = scanner.getIncludedFiles(); | String[] scannedFiles = scanner.getIncludedFiles(); | ||||
| @@ -157,7 +159,18 @@ public class DependTest extends BuildFileTest { | |||||
| for (int i = 0; i < scannedFiles.length; ++i) { | for (int i = 0; i < scannedFiles.length; ++i) { | ||||
| files.put(scannedFiles[i], scannedFiles[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()); | |||||
| } | } | ||||
| } | } | ||||