Whew, I've got it! Matt, thanks for your sample JUnit testcase. I should have guessed the real reason sooner. This is not an issue with <junit> per se but rather with ANT itself [specifically with the way Execute class forks a VM {which is different from how forkable tasks like <java> work} combined with how ANT is packaged].
Basically, ANT ships with several jars that contain manifest Class-Path attributes pointing to each other, e.g. Manifest-Version: 1.0 Main-Class: org.apache.tools.ant.Main Created-By: Ant 1.4 Class-Path: jaxp.jar parser.jar crimson.jar optional.jar xalan.jar There are at least two jars like that: ant.jar and the optional tasks jar. Both of these jars percolate to the -classpath of the JVM forked by Execute. The Class-Path attributes in their manifests effectively place the entire set {jaxp.jar, parser.jar, crimson.jar, optional.jar, xalan.jar} into the application classpath. The thing that threw me off was that such classpath entries will not show up either in java.class.path system property or java.net.URLClassLoader.getURLs () -- a pretty good reason never to use manifest files with Class-Path, if you ask me. Anyway, that's how crimson.jar found its way into the forked VM in a completely silent fashion... I leave the proper resolution up to the dev team, but for you the workaround would be to edit or delete the manifest.mf files in the two jars I mentioned above. Not ideal, but better than patching ANT code yourself. Vlad. To: <[EMAIL PROTECTED]> cc: Subject: RE: forked JVM's classpath not clean when using JUnit task Vlad, You are quite a detective! Here's the output (below). As I suspected, crimson.jar is sneaking in there. I guess the question now is, "how?" As you requested, I've directed this message to you only. I'm glad that you're interested in my problem, as you have a good grasp on classloading in general. At this point, it seems to me that a close reading of the JunitTask source code is necessary to fix the problem, and I'm not sure that I'm up to doing that. I have a custom test runner of my own that I can wire in to ant for a quick fix that will work for my current needs. I do plan on attacking this problem later on, however, so if you have any more ideas on this issue (which I am now certain *is* a defect), I'd be glad to hear them. [junit] resource for crimson == jar:file:/D:/programs/jakarta-ant-1.4.1/lib/crimson.jar!/org/apache/crimson/ parser/X MLReaderImpl.class [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.221 sec - Matt -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Thursday, January 24, 2002 9:59 AM To: Ant Users List Subject: RE: forked JVM's classpath not clean when using JUnit task The "current loader" shown below is the usual Java 2 application classloader, not a custom JUnit one.... Bummer, that blows my first clue away. If you absolutely sure none of the other jars contains crimson classes (what are those parser.jar and xml.jar?) then hmmm.... Ok, I feel challenged now. I've thought of another trick that is even better than my previous one. Luckily, Sun JVMs allow retrieving classes as resource URLs and those, when converted to a String, give away the actual disk location of a class. So, add another line to your testcase that does this: System.out.println (getClass().getClassLoader().getResource ("org/apache/crimson/parser/XMLReaderImpl.class")); and let us know. Or you can just email me only, 'cause I am beginning to suspect that we are starting to annoy the rest of the list... Vlad. Please respond to "Ant Users List" <[EMAIL PROTECTED]> To: "Ant Users List" <[EMAIL PROTECTED]> cc: Subject: RE: forked JVM's classpath not clean when using JUnit task Vlad & list, Thanks again for all your insightful suggestions. I created the test you suggested, and have included my output below. Unfortunately, crimson.jar is not listed there. Perhaps the classpath the loader is using and the java.class.path variable are different? Is this possible? Could someone out there who has experience with the junit task please respond to this thread? If the classpath isn't being set properly, there is likely a serious defect in the task that would prevent many developers from using it. If at all possible, this defect should be tracked down and removed, or at least a workaround should be found. [junit] app classpath = D:\programs\jakarta-ant-1.4.1\lib\junit.jar;D:\programs\jakarta-ant-1.4.1\li b\ant.jar;D:\pro grams\jakarta-ant-1.4.1\lib\jakarta-ant-1.4.1-optional.jar;D:\Matt\apelon\vs s\dev200104\build\tests\ApelonCommon\jars\Te stApelonCommon.jar;D:\Matt\apelon\vss\dev200104\build\dist\lib\ApelonCommon. jar;D:\Matt\apelon\vss\dev200104\jars\log4j. jar;D:\Matt\apelon\vss\dev200104\jars\parser.jar;D:\Matt\apelon\vss\dev20010 4\jars\xml.jar [junit] current loader = sun.misc.Launcher$AppClassLoader@71732b [junit] user.home == C:\Documents and Settings\mmunz - Matt -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Wednesday, January 23, 2002 3:42 PM To: Ant Users List Subject: RE: forked JVM's classpath not clean when using JUnit task Ok, sorry about not being able to help you more right now but I can't take any more time away from work at this point. I've looked into junit task code [I only have ANT 1.4] and that seems to eventually fork a JVM correctly. Unless someone else sorts this out in the meantime, I leave you with these clues for now: - during the fork the JUnitTest class exports all ANT project properties into a temp props file that is later picked up by the JUnitTestRunner class in a forked JVM. The idea is to resurrect the Java runtime as closely as possible. Well, one of the properties exported is of course "java.class.path" and it will look something like this from ANT source JVM [note crimson.jar]: java.class.path: D:\J\JDK1.3\lib\tools.jar;D:\ANT\lib\jaxp.jar;D:\ANT\lib\jakarta-ant-1.4-opt ional.jar;D:\ANT\lib\crimson.jar;D:\ANT\lib\ant.jar; JUnitTestRunner will later absorb these into the forked JVM. Next, normally just setting java.class.path post-bootstrap [like in main() or later] will not have an effect on the normal app classloader, but [!] I happened to know that JUnit made use of its own custom classloader. I happened to have v3.7 sources in the office and I looked at the classloader impl: lo and behold, the first thing it does is set its classpath from "java.class.path" property. Anyway, I am not convinced that when JUnit is executed from <junit> task the same init sequence takes place as when running JUnit standalone but this is my strongest clue so far. If this proves to be correct, try disabling JUnit classloader [I remember it has a property for that]. - if the above is a wrong clue, you could get some more data by adding a quick pseudo-TestCase to you suite and have it output the following: System.out.println ("app classpath = " + System.getProperty ("java.class.path")); System.out.println ("current loader = " + getClass().getClassLoader()); Hope this helps, Vlad. Please respond to "Ant Users List" <[EMAIL PROTECTED]> To: "Ant Users List" <[EMAIL PROTECTED]> cc: Subject: RE: forked JVM's classpath not clean when using JUnit task Vlad and list, > Is the JVM really forked as you made me think? Otherwise all ANT classes > have access to crimson classes because it is seen by AntClassLoader.... I have indicated that I want it to be forked, and the build output seems to indicate this. I can't know however, wether or not it actually does run on a forked JVM. I've included the relevant build file snippet (below) in case it helps in your diagnosis. In browsing the bug-tracking system for junit-related cases, I've noticed that the junit task has produced buggy behavior in the past, so it's possible that the junit task is responsible for this error (rather than the more commonly used ant code). Are there any people on this list who are familiar with the junit task specifically? If so, I'd love to hear from them about this. Thanks again for your help with this issue. <junit fork="true" printsummary="yes" haltonfailure="no" failureProperty="test-failed"> <classpath> <pathelement path="${test-proj-path}/jars/Test${jar-name}.jar" /> <pathelement path="${LIB.DIR}/${jar-name}.jar" /> <pathelement path="${classpath-ext}" /> </classpath> <formatter type="xml" /> <batchtest fork="true" todir="${reports-dir}"> <fileset dir="${tests-src-dir}"> <include name="**/${pkg-path}/**/Test*.java" /> </fileset> </batchtest> </junit> - Matt -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Wednesday, January 23, 2002 2:39 PM To: Ant Users List Subject: RE: forked JVM's classpath not clean when using JUnit task Is the JVM really forked as you made me think? Otherwise all ANT classes have access to crimson classes because it is seen by AntClassLoader.... Please respond to "Ant Users List" <[EMAIL PROTECTED]> To: "Ant Users List" <[EMAIL PROTECTED]> cc: Subject: RE: forked JVM's classpath not clean when using JUnit task Vlad, Thanks for your reply. > - if crimson is in your JRE ext directory, removing it from the task's > classpath won't make a difference. not the case here > - are you sure you are not including the crimson classes through one of > the other jars? How about the CLASSPATH env var? all of these things do not contain the crimson class files. Any other ideas? - Matt -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Wednesday, January 23, 2002 12:27 PM To: Ant Users List Subject: Re: forked JVM's classpath not clean when using JUnit task I am not familiar with junit task but I can make these comments: - if crimson is in your JRE ext directory, removing it from the task's classpath won't make a difference. - are you sure you are not including the crimson classes through one of the other jars? How about the CLASSPATH env var? Vlad. Please respond to "Ant Users List" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> cc: Subject: forked JVM's classpath not clean when using JUnit task Hi. I am aware that the answer to this may already be in the archives. They are not available at the moment, however, so I thought I'd ask all of you for your help. If there is a mirror to the mail archive, or another resource that covers this issue, I'd be happy to read it. Problem (w2k., ant 1.4.1): When building a project that includes a junit task, it is apparent that crimson.jar is accessible from the JUnitTestRunner. This is undesireable, as my test should have no knowledge / access to crimson.jar. I see this behavior even when the fork attribute to my junit task is set to true. As the output (below) shows, the execution of java.exe has the classpath arg set to a path that does not include crimson.jar. According to the docs for java.exe, this path should override any classpath set in the System's environment variables. Nonetheless, the output from my test clearly indicates that crimson.jar is available to the test runner (and test). Is there a way to fix this so that I can cleanly (w/o crimson.jar on the classpath) run my tests? Output (verbose): run-test-package: [junit] Running com.apelonTests.common.dom.TestApelDOMParser [junit] Executing: d:\programs\jdk1.3.1_01\jre\..\bin\java.exe -classpath D:\programs\jakarta-ant-1.4.1\lib\junit.ja r;D:\programs\jakarta-ant-1.4.1\lib\ant.jar;D:\programs\jakarta-ant-1.4.1\li b\jakarta-ant-1.4.1-optional.jar;D:\Matt\ape lon\vss\dev200104\build\tests\ApelonCommon\jars\TestApelonCommon.jar;D:\Matt \apelon\vss\dev200104\build\dist\lib\ApelonC ommon.jar;D:\Matt\apelon\vss\dev200104\jars\log4j.jar;D:\Matt\apelon\vss\dev 200104\jars\parser.jar;D:\Matt\apelon\vss\de v200104\jars\xml.jar org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner com.apelonTests.common.dom.TestApelDOM Parser haltOnError=false haltOnFailure=false formatter=org.apache.tools.ant.taskdefs.optional.junit.SummaryJUnitResultFo rmatter formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatt er,D:\Matt\apelon\vss\dev200104\buil d\tests\ApelonCommon\reports\TEST-com.apelonTests.common.dom.TestApelDOMPars er.xml propsfile=D:\Matt\apelon\vss\Dev20010 4\build\tests\junit4486939605375226940.properties [junit] org.xml.sax.SAXParseException: Element type "s" is not declared. [junit] at org.apache.crimson.parser.Parser2.error(Parser2.java:3086) [junit] at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1316) [junit] at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:500) [junit] at org.apache.crimson.parser.Parser2.parse(Parser2.java:305) [junit] at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:433) [junit] at org.xml.sax.helpers.XMLReaderAdapter.parse(XMLReaderAdapter.java:223) [junit] at com.apelon.common.dom.ApelDOMParser.parse(Unknown Source) [junit] at com.apelonTests.common.dom.TestApelDOMParser.testParse(Unknown Source) [junit] at java.lang.reflect.Method.invoke(Native Method) [junit] at junit.framework.TestCase.runTest(TestCase.java:166) [junit] at junit.framework.TestCase.runBare(TestCase.java:140) [junit] at junit.framework.TestResult$1.protect(TestResult.java:106) [junit] at junit.framework.TestResult.runProtected(TestResult.java:124) [junit] at junit.framework.TestResult.run(TestResult.java:109) [junit] at junit.framework.TestCase.run(TestCase.java:131) [junit] at junit.framework.TestSuite.runTest(TestSuite.java:173) [junit] at junit.framework.TestSuite.run(TestSuite.java:168) [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRu nner.java:231) [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestR unner.java:409) Thanks in advance for any help you can offer. - Matt Munz ([EMAIL PROTECTED]) -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>