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()); | |||||
} | } | ||||
} | } |