]> source.dussan.org Git - aspectj.git/commitdiff
harness LTW support - untested
authorwisberg <wisberg>
Thu, 12 May 2005 11:54:22 +0000 (11:54 +0000)
committerwisberg <wisberg>
Thu, 12 May 2005 11:54:22 +0000 (11:54 +0000)
testing/src/org/aspectj/testing/harness/bridge/CompilerRun.java
testing/src/org/aspectj/testing/harness/bridge/JavaRun.java
testing/src/org/aspectj/testing/harness/bridge/Sandbox.java
testing/src/org/aspectj/testing/xml/AjcSpecXmlReader.java
tests/ajcHarnessTests.xml
tests/ajcTestSuite.dtd
tests/harness/fork/MainWriter.java [new file with mode: 0644]

index 0ab12ebb30b39fa617371c5811a9341884f24e82..8f1935267f7e35032a6e9ccf65aa92ad4f1b3fa6 100644 (file)
@@ -148,7 +148,6 @@ public class CompilerRun implements IAjcRun {
                 return false;
             }
         }
-        sandbox.setTestBaseSrcDir(testBaseSrcDir, this);
 
         // Sources come as relative paths - check read, copy if staging.
         // This renders paths absolute before run(RunStatusI) is called.
@@ -179,9 +178,7 @@ public class CompilerRun implements IAjcRun {
         // validate readable for sources
         if (!spec.badInput) {
             if (!validator.canRead(testBaseSrcDir, srcPaths, "sources")
-                // moved validation of inpathPaths below due to ambiguous base dir
-                //|| !validator.canRead(testBaseSrcDir, injarPaths, "injars")
-                //|| !validator.canRead(testBaseSrcDir, inpathPaths, "inpaths")
+                // see validation of inpathPaths below due to ambiguous base dir
                 || !validator.canRead(
                     testBaseSrcDir,
                     spec.argfiles,
@@ -401,11 +398,8 @@ public class CompilerRun implements IAjcRun {
         }
         cp[index++] = Globals.F_aspectjrt_jar;
         cp[index++] = Globals.F_testingclient_jar;
-        sandbox.setClasspath(cp, checkReadable, this);
-        // set aspectpath
-        if (0 < aspectFiles.length) {
-            sandbox.setAspectpath(aspectFiles, checkReadable, this);
-        }
+        sandbox.compilerRunInit(this, testBaseSrcDir, aspectFiles,
+                checkReadable, cp, checkReadable, null);
 
         // XXX todo set bootclasspath if set for forking?
         return true;
@@ -439,9 +433,7 @@ public class CompilerRun implements IAjcRun {
             MessageUtil.abort(status, spec.testSetup.failureReason);
             return false;
         }
-//        boolean ignoreWarnings =
-//            (spec.testSetup.ignoreWarningsSet
-//                && spec.testSetup.ignoreWarnings);
+
         AjcMessageHandler handler =
             new AjcMessageHandler(spec.getMessages());
         handler.init();
index 916b69bc25bc0ca40dd88ef899c4e7b577c565d8..7a16e25d5c5fc90dc18e93b8aea36ba1c33a1291 100644 (file)
@@ -12,6 +12,7 @@
 
 package org.aspectj.testing.harness.bridge;
 
+import org.aspectj.bridge.AbortException;
 import org.aspectj.bridge.IMessageHandler;
 import org.aspectj.bridge.MessageUtil;
 import org.aspectj.testing.Tester;
@@ -23,6 +24,7 @@ import org.aspectj.testing.xml.SoftMessage;
 import org.aspectj.testing.xml.XMLWriter;
 import org.aspectj.util.FileUtil;
 import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.WeavingURLClassLoader;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -78,7 +80,8 @@ public class JavaRun implements IAjcRun {
      * @see org.aspectj.testing.harness.bridge.AjcTest.IAjcRun#setup(File, File)
         */
        public boolean setupAjcRun(Sandbox sandbox, Validator validator) {
-               this.sandbox = sandbox;        
+               this.sandbox = sandbox;
+        sandbox.javaRunInit(this);
                return (validator.nullcheck(spec.className, "class name")
             && validator.nullcheck(sandbox, "sandbox")
             && validator.canReadDir(sandbox.getTestBaseSrcDir(this), "testBaseSrc dir")
@@ -98,6 +101,7 @@ public class JavaRun implements IAjcRun {
                 ClassNotFoundException,
                 NoSuchMethodException {
         boolean completedNormally = false;
+        boolean passed = false;
         if (!LangUtil.isEmpty(spec.dirChanges)) {
             MessageUtil.info(status, "XXX dirChanges not implemented in JavaRun");
         }
@@ -106,31 +110,70 @@ public class JavaRun implements IAjcRun {
             File[] libs = sandbox.getClasspathJars(readable, this);
             boolean includeClassesDir = true;
             File[] dirs = sandbox.getClasspathDirectories(readable, this, includeClassesDir);
-            completedNormally = (spec.forkSpec.fork || !LangUtil.isEmpty(spec.aspectpath))
+            completedNormally = (spec.forkSpec.fork)
                 ? runInOtherVM(status, libs, dirs)
                 : runInSameVM(status, libs, dirs);
+            passed = completedNormally;
         } finally {
-            if (!completedNormally  || !status.runResult()) {
+            if (!passed  || !status.runResult()) {
                 MessageUtil.info(status, spec.toLongString());
                 MessageUtil.info(status, "sandbox: " + sandbox);
             }
         }
-        return completedNormally;
+        return passed;
     }
     protected boolean runInSameVM(IRunStatus status, File[] libs, File[] dirs) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
         ClassLoader loader = null;
-        URL[] urls = FileUtil.getFileURLs(libs);
         boolean completedNormally = false;
+        boolean passed = false;
+        ByteArrayOutputStream outSnoop = null;
+        PrintStream oldOut = null;
+        ByteArrayOutputStream errSnoop = null;
+        PrintStream oldErr = null;
         if (spec.outStreamIsError) {
-            // XXX implement same-vm stream snooping
-            // strictly speaking, also warn for errStream, but 
-            // it is on by default (in same-VM, Tester controls;
-            // in other-vm stream-snooping controls)
-            MessageUtil.info(status, "unimplemented: stream-based error implemented in same vm");
+            outSnoop = new ByteArrayOutputStream();
+            oldOut = System.out;
+            System.setOut(new PrintStream(outSnoop, true));
+        }
+        if (spec.errStreamIsError) {
+            errSnoop = new ByteArrayOutputStream();
+            oldErr = System.err;
+            System.setErr(new PrintStream(errSnoop, true));
         }
         Class targetClass = null;
         try {
-            loader = new TestClassLoader(urls, dirs);
+            final URL[] clAndLibs;
+            {
+                File[] files = sandbox.findFiles(spec.classpath);
+                URL[] clURLs = FileUtil.getFileURLs(files);
+                URL[] libURLs = FileUtil.getFileURLs(libs);
+                clAndLibs = new URL[clURLs.length + libURLs.length];
+                System.arraycopy(clURLs, 0, clAndLibs , 0, clURLs.length);
+                System.arraycopy(libURLs, 0, clAndLibs, clURLs.length, libURLs.length);
+            }
+            if (!spec.isLTW()) {
+                loader = new TestClassLoader(clAndLibs, dirs);                
+            } else {
+                final URL[] aspectURLs;
+                {
+                    File[] files = sandbox.findFiles(spec.aspectpath);
+                    aspectURLs = FileUtil.getFileURLs(files);
+                }
+                ArrayList classpath = new ArrayList();
+                classpath.addAll(Arrays.asList(aspectURLs));
+                final URL[] classURLs;
+                {
+                    classpath.addAll(Arrays.asList(clAndLibs));
+                    URL[] urls = FileUtil.getFileURLs(dirs);
+                    classpath.addAll(Arrays.asList(urls));
+                    classpath.add(FileUtil.getFileURL(Globals.F_aspectjrt_jar));
+                    classpath.add(FileUtil.getFileURL(Globals.F_testingclient_jar));
+                    classURLs = (URL[]) classpath.toArray(new URL[0]);
+                }
+                
+                ClassLoader parent = JavaRun.class.getClassLoader();
+                loader = new WeavingURLClassLoader(classURLs, aspectURLs, parent);
+            }
             // make the following load test optional
             // Class testAspect = loader.loadClass("org.aspectj.lang.JoinPoint");
             targetClass = loader.loadClass(spec.className);
@@ -139,6 +182,16 @@ public class JavaRun implements IAjcRun {
             RunSecurityManager.ME.setJavaRunThread(this);
             main.invoke(null, new Object[] { spec.getOptionsArray() });
             completedNormally = true;
+            boolean snoopFailure =
+                ((null != errSnoop) && 0 < errSnoop.size())
+                || ((null != outSnoop) && 0 < outSnoop.size());
+            passed = !snoopFailure && (null == spec.expectedException);
+        } catch (AbortException e) {
+            if (expectedException(e)) {
+                passed = true;
+            } else {
+                throw e;
+            }
         } catch (InvocationTargetException e) {
             // this and following clauses catch ExitCalledException
             Throwable thrown = LangUtil.unwrapException(e);
@@ -152,6 +205,8 @@ public class JavaRun implements IAjcRun {
                 MessageUtil.fail(status, "test code should not use the AWT event queue");
                 throw (RunSecurityManager.AwtUsedException) thrown;
                 // same as: status.thrown(thrown);
+            } else if (expectedException(thrown)) {
+                passed = true;
             } else if (thrown instanceof RuntimeException) {
                 throw (RuntimeException) thrown;
             } else if (thrown instanceof Error) {
@@ -167,13 +222,19 @@ public class JavaRun implements IAjcRun {
             MessageUtil.info(status, "sandbox.classes: " + Arrays.asList(classes));
             MessageUtil.fail(status, null, e);
         } finally {
+            if (null != oldOut) {
+                System.setOut(oldOut);
+            }
+            if (null != oldErr) {
+                System.setErr(oldErr);
+            }
             RunSecurityManager.ME.releaseJavaRunThread(this);
             if (!completedNormally) {
                 MessageUtil.info(status, "targetClass: " + targetClass);
                 MessageUtil.info(status, "loader: " + loader);
             }
         }
-        return completedNormally;
+        return passed;
     }
     
     /**
@@ -198,9 +259,19 @@ public class JavaRun implements IAjcRun {
             appendClasspath(cp, spec.forkSpec.bootclasspath);
             appendClasspath(cp, dirs);        
             appendClasspath(cp, libs);
+            File[] classpathFiles = sandbox.findFiles(spec.classpath);
+            int cpLength = (null == classpathFiles ? 0 : classpathFiles.length);
+            int spLength = (null == spec.classpath ? 0 : spec.classpath.length);
+            if (cpLength != spLength) {
+                throw new Error("unable to find " + Arrays.asList(spec.classpath)
+                        + " got " + Arrays.asList(classpathFiles));
+            }
+            appendClasspath(cp, classpathFiles);
+            File[] stdlibs = {Globals.F_aspectjrt_jar, Globals.F_testingclient_jar};
+            appendClasspath(cp, stdlibs);
             classpath = cp.toString();
         }
-        if (LangUtil.isEmpty(spec.aspectpath)) {
+        if (!spec.isLTW()) {
             cmd.add("-classpath");
             cmd.add(classpath);
         } else {
@@ -209,11 +280,12 @@ public class JavaRun implements IAjcRun {
                 throw new Error("load-time weaving test requires Java 1.4+");
             }
             cmd.add("-Djava.system.class.loader=org.aspectj.weaver.WeavingURLClassLoader");
+            // assume harness VM classpath has WeavingURLClassLoader (but not others)
             cmd.add("-classpath");
             cmd.add(System.getProperty("java.class.path"));
 
             File[] aspectJars = sandbox.findFiles(spec.aspectpath);
-            if (LangUtil.isEmpty(aspectJars)) {
+            if (aspectJars.length != spec.aspectpath.length) {
                 throw new Error("unable to find " + Arrays.asList(spec.aspectpath));
             }
             StringBuffer cp = new StringBuffer();
@@ -231,6 +303,7 @@ public class JavaRun implements IAjcRun {
         class DoneFlag {
             boolean done;
             boolean failed;
+            int code;
         }
         final StringBuffer commandLabel = new StringBuffer();
         final DoneFlag doneFlag = new DoneFlag();
@@ -247,13 +320,13 @@ public class JavaRun implements IAjcRun {
                         + commandLabel 
                         + "\"";
                     if (null != ex.fromProcess) {
-                        String m = "Exception running " + context;
-                        MessageUtil.abort(handler, m, ex.fromProcess);
-                        doneFlag.failed = true;
+                        if (!expectedException(ex.fromProcess)) {
+                            String m = "Exception running " + context;
+                            MessageUtil.abort(handler, m, ex.fromProcess);
+                            doneFlag.failed = true;
+                        }
                     } else if (0 != result) {
-                        String m = result + " result code from running " + context;
-                        MessageUtil.fail(handler, m);
-                        doneFlag.failed = true;
+                        doneFlag.code = result;
                     }
                     if (null != ex.fromInPipe) {
                         String m = "Error processing input pipe for " + context;
@@ -306,8 +379,12 @@ public class JavaRun implements IAjcRun {
                 // ignore
             }
         }
+
+        boolean foundException = false;
         if (0 < errSnoop.size()) {
-            if (spec.errStreamIsError) {
+            if (expectedException(errSnoop)) {
+                foundException = true;
+            } else if (spec.errStreamIsError) {
                 MessageUtil.error(handler, errSnoop.toString());
                 if (!doneFlag.failed) {
                     doneFlag.failed = true;
@@ -317,7 +394,9 @@ public class JavaRun implements IAjcRun {
             }
         }
         if (0 < outSnoop.size()) {
-            if (spec.outStreamIsError) {
+            if (expectedException(outSnoop)) {
+                foundException = true;
+            } else if (spec.outStreamIsError) {
                 MessageUtil.error(handler, outSnoop.toString());
                 if (!doneFlag.failed) {
                     doneFlag.failed = true;
@@ -326,11 +405,37 @@ public class JavaRun implements IAjcRun {
                 MessageUtil.info(handler, "Output stream: " + outSnoop.toString());
             }
         }
+        if (!foundException) {
+            if (null != spec.expectedException) {
+                String m = " expected exception " + spec.expectedException;
+                MessageUtil.fail(handler, m);                
+                doneFlag.failed = true;
+            } else if (0 != doneFlag.code) {
+                String m = doneFlag.code + " result from " + commandLabel;
+                MessageUtil.fail(handler, m);
+                doneFlag.failed = true;
+            }
+        }
         if (doneFlag.failed) {
             MessageUtil.info(handler, "other-vm command-line: " + commandLabel);
         }
         return !doneFlag.failed;
     }
+
+    protected boolean expectedException(Throwable thrown) {
+        if (null != spec.expectedException) {
+            String cname = thrown.getClass().getName();
+            if (-1 != cname.indexOf(spec.expectedException)) {
+                return true; // caller sets value for returns normally
+            }
+        }
+        return false;
+    }
+    
+    protected boolean expectedException(ByteArrayOutputStream bout) {
+        return ((null != spec.expectedException)
+                && (-1 != bout.toString().indexOf(spec.expectedException)));
+    }
     
     /**
      * Clear (static) testing state and setup base directory,
@@ -518,6 +623,9 @@ public class JavaRun implements IAjcRun {
         
         protected final ForkSpec forkSpec;
         protected String[] aspectpath;
+        protected boolean useLTW;
+        protected String[] classpath;
+        protected String expectedException;
         
         public Spec() {
             super(XMLNAME);
@@ -542,6 +650,10 @@ public class JavaRun implements IAjcRun {
             return result;    
         }
 
+        public boolean isLTW() {
+            return useLTW || (null != aspectpath);
+        }
+        
         /**
          * @param version "1.1", "1.2", "1.3", "1.4"
          * @throws IllegalArgumentException if version is not recognized
@@ -556,15 +668,26 @@ public class JavaRun implements IAjcRun {
             this.className = className;
         }
         
+        public void setLTW(String ltw) {
+            useLTW = Boolean.parseBoolean(ltw);
+        }
+        
         public void setAspectpath(String path) {
             this.aspectpath = XMLWriter.unflattenList(path);
         }
-        public void setErrStreamIsError(boolean errStreamIsError) {
-            this.errStreamIsError = errStreamIsError;
+        public void setException(String exception) {
+            this.expectedException = exception;
+        }
+        
+        public void setClasspath(String path) {
+            this.classpath = XMLWriter.unflattenList(path);
+        }
+        public void setErrStreamIsError(String errStreamIsError) {
+            this.errStreamIsError = Boolean.parseBoolean(errStreamIsError);
         }
 
-        public void setOutStreamIsError(boolean outStreamIsError) {
-            this.outStreamIsError = outStreamIsError;
+        public void setOutStreamIsError(String outStreamIsError) {
+            this.outStreamIsError = Boolean.parseBoolean(outStreamIsError);
         }
 
         /** @param skip if true, then do not set up Tester */
index 9a89e4f45a7fa531b3f36dfdf6688de6672f419d..9388cf84e8c9d4bdcf06664309e6bc9a45fb597d 100644 (file)
@@ -128,6 +128,8 @@ public class Sandbox {
     /** cache results of rendering final fields */
     private transient String toStringLeader;
     
+    private transient boolean compilerRunInit;
+    
     /** @throws IllegalArgumentException unless validator validates
      *           testBaseDir as readable
      */
@@ -353,8 +355,47 @@ public class Sandbox {
         return testBaseSrcDir;
     }
     
+    void defaultTestBaseSrcDir(JavaRun caller) {
+        LangUtil.throwIaxIfNull(caller, "caller");
+        if (null != testBaseSrcDir) {
+            throw new IllegalStateException("testBaseSrcDir not null");
+        }
+        testBaseSrcDir = testBaseDir;
+    }
+    
+    static boolean readableDir(File dir) {
+        return ((null != dir) && dir.isDirectory() && dir.canRead());
+    }
+
+    void compilerRunInit(CompilerRun caller, File testBaseSrcDir,
+            File[] aspectPath, boolean aspectpathReadable,
+            File[] classPath, boolean classpathReadable,
+            String bootclassPath
+            ) {
+        if (null != testBaseSrcDir) {
+            setTestBaseSrcDir(testBaseSrcDir, caller);
+        }
+        if ((null != aspectPath) && (0 < aspectPath.length)) {
+            setAspectpath(aspectPath, aspectpathReadable, caller);
+        }
+        if ((null != classPath) && (0 < classPath.length)) {
+            setClasspath(classPath, classpathReadable, caller);
+        }
+        
+        setBootclasspath(bootclassPath, caller);
+        compilerRunInit = true;
+    }
+    void javaRunInit(JavaRun caller) {
+        if (!compilerRunInit) {
+            testBaseSrcDir = testBaseDir;
+            // default to aspectjrt.jar?
+            compileClasspath = new File[0]; 
+            
+        }
+    }
+
     /** @throws IllegalArgumentException unless a readable directory */
-    void setTestBaseSrcDir(File dir, CompilerRun caller) {
+    private void setTestBaseSrcDir(File dir, CompilerRun caller) {
         LangUtil.throwIaxIfNull(caller, "caller");
         if ((null == dir) || !dir.isDirectory() || !dir.canRead()) {
             throw new IllegalArgumentException("bad test base src dir: " + dir);
@@ -366,7 +407,7 @@ public class Sandbox {
      * Set aspectpath.
      * @param readable if true, then throw IllegalArgumentException if not readable 
      */
-    void setAspectpath(File[] files, boolean readable, CompilerRun caller) {
+    private void setAspectpath(File[] files, boolean readable, CompilerRun caller) {
         LangUtil.throwIaxIfNull(files, "files");
         LangUtil.throwIaxIfNull(caller, "caller");
         assertState(null == aspectpath, "aspectpath already written");
@@ -386,7 +427,7 @@ public class Sandbox {
      * @param bootClasspath
      * @param caller
      */
-    void setBootclasspath(String bootClasspath, CompilerRun caller) {
+    private void setBootclasspath(String bootClasspath, CompilerRun caller) {
         this.bootClasspath = bootClasspath;
     }
     
@@ -394,7 +435,7 @@ public class Sandbox {
      * Set compile classpath.
      * @param readable if true, then throw IllegalArgumentException if not readable 
      */
-    void setClasspath(File[] files, boolean readable, CompilerRun caller) {
+    private void setClasspath(File[] files, boolean readable, CompilerRun caller) {
         LangUtil.throwIaxIfNull(files, "files");
         LangUtil.throwIaxIfNull(caller, "caller");
         assertState(!gotClasspath, "classpath already read");
@@ -520,7 +561,7 @@ public class Sandbox {
         public boolean accept(File file) {
             if (null != file) {
                 String name = file.getName();
-                if (null != name) {
+                if ((null != name) && (null != names)) {
                     for (int i = 0; i < names.length; i++) {
                         if (name.equals(names[i])) {
                             return true;
index 669be001f3f4469bde4996f3abaa176b436ea529..28912a02662b5d0b607680ca7ee9be7077153c94 100644 (file)
@@ -360,8 +360,14 @@ public class AjcSpecXmlReader {
         jrunspec.addMessage((IMessage) null);
         // input s.b. interpretable by Boolean.valueOf(String)
         jrunspec.setSkipTester(true); 
-        jrunspec.setErrStreamIsError(true);
-        jrunspec.setOutStreamIsError(true);
+        jrunspec.setErrStreamIsError("false");
+        jrunspec.setOutStreamIsError("false");
+        jrunspec.setAspectpath("");
+        jrunspec.setClasspath("");
+        jrunspec.setFork(false);
+        jrunspec.setLTW("false");
+        jrunspec.setException("Error");
+        
         
         DirChanges.Spec dcspec = new DirChanges.Spec();
         dcspec.setAdded((String) null);
index ebcee1d9535bb49e38169ff40030319b83253a8f..fc393ca3c97116b7daaad8f7695b8105b4248c36 100644 (file)
         PASS fail {title..}  # expect fail, actual pass
 
      Also pick out "incremental-test" keyword for incremental tests.
+        
+        Variant tests below:
+        - [fork|spoon]-[out|err|Error]-[detected|ignored]
+        - ltw-[base|jarAspectpath{-jarClasspath}]
+        
+        Issues:
+        - harness not stopping after unexpected-fails completes.
+          When exception thrown, everything cleaned up?
+
 -->
 <suite>
 <!-- disabled so skipping expect-fail causes all to pass
@@ -24,6 +33,7 @@
         <compile files="NoSuchFile.java"/>
     </ajc-test>
 -->
+
     <ajc-test dir="harness"
       title="pass 2 error">
         <compile files="ErrorTest.java">
 
         <inc-compile tag="same" fresh="true" />
                <run class="packageOne.Main" 
-                  options="new-event"/> <!-- now expect new-event -->
+                  options="new-event"/>
     </ajc-test>
     
     <ajc-test dir="harness"  keywords="incremental-test"
                </inc-compile>
     </ajc-test>
        
-    <!--ajc-test dir="harness"
+    <ajc-test dir="harness"
        keywords="expect-fail"
                title="fail not forking or setting property">
         <compile files="SystemPropertiesTest.java"/>
                fork="true" 
                vmargs="-DPASS=true,-Dname=value"/>
     </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass fork verify Main runs">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" fork="true"/> 
+    </ajc-test>
+       
+    <ajc-test dir="harness/fork"
+               title="pass spoon verify Main runs">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail fork-err-detected Main runs, uses System.err, fails on err">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="err" fork="true"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass fork-err-ignored Main runs, uses System.err, err ignored">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="err" fork="true" errStreamIsError="false"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail fork-out-detected Main runs, uses System.out, fails on out">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="out" fork="true" outStreamIsError="true"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass fork-out-ignored Main runs, uses System.out, out ignored">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="out" fork="true" outStreamIsError="false"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail fork-Error-detected Main runs, throws Error, fails on Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="Error" fork="true" /> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass fork-Error-ignored Main runs, throws Error, expects Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="Error" fork="true" exception="Error"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail fork-Error-missed Main runs, does not throws Error, expects Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" fork="true" exception="Error"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail spoon-err-detected Main runs, uses System.err, fails on err">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="err" /> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass spoon-err-ignored Main runs, uses System.err, err ignored">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="err" errStreamIsError="false"/> 
+    </ajc-test>
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail spoon-out-detected Main runs, uses System.out, fails on out">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="out" outStreamIsError="true"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass spoon-out-ignored Main runs, uses System.out, out ignored">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="out" outStreamIsError="false"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail spoon-Error-detected Main runs, throws Error, fails on Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="Error"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               title="pass spoon-Error-ignored Main runs, throws Error, expects Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="Error" exception="Error"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/fork"
+               keywords="expect-fail"
+               title="fail spoon-Error-missed Main runs, does not throws Error, expects Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" exception="Error"/> 
+    </ajc-test>
+       
     <ajc-test dir="harness/aspectpath"
-               title="pass aspectpath LTW aspect works in one compile">
-        <compile files="A.java,Main.java"/>
+               keywords="expect-fail"
+               title="fail ltw-base Main fails without aspect">
+        <compile files="Main.java"/>
         <run class="Main"/> 
     </ajc-test>
 
     <ajc-test dir="harness/aspectpath"
-               keywords="expect-fail"
-               title="fail aspectpath LTW failure case">
+               title="pass ltw-base Main fails without aspect (expected)">
         <compile files="Main.java"/>
+        <run class="Main" exception="Error"/> 
+    </ajc-test>
+
+    <ajc-test dir="harness/aspectpath"
+               title="pass ltw-base Main works with aspect">
+        <compile files="A.java,Main.java"/>
         <run class="Main"/> 
-    </ajc-test-->
+    </ajc-test>
 
-       <!-- uncomment after weaveinfo messages 
-         (which cause false negatives) are suppressed
     <ajc-test dir="harness/aspectpath"
-               title="pass aspectpath LTW">
+               title="pass ltw-jarAspectpath">
         <compile files="A.java" outjar="out.jar"/>
         <compile files="Main.java"/>
         <run class="Main" aspectpath="out.jar"/> 
     </ajc-test>
-    -->
 
+    <ajc-test dir="harness/aspectpath"
+               title="pass ltw-jarAspectpath-jarClasspath">
+        <compile files="A.java" outjar="out.jar"/>
+        <compile files="Main.java" outjar="cl.zip"/>
+        <run class="Main" aspectpath="out.jar" classpath="cl.zip"/> 
+    </ajc-test>
+
+<!-- reproduce hang from blocking IO read at JavaRun.java 
+    <ajc-test dir="harness/fork"
+               title="pass fork-Error-ignored Main runs, throws Error, expects Error">
+        <compile files="MainWriter.java"/>
+        <run class="MainWriter" options="Error" fork="true" exception="Error"/> 
+    </ajc-test>
+-->
 </suite>
 
 
index e7c4f5918cc457ccb4c679c6d405893e2da373ca..44734a9ccb71cd789d8026c09d84a8edfb76a0a0 100644 (file)
@@ -4,8 +4,8 @@
 \r
    <!ELEMENT suite (ajc-test*)>\r
    <!ATTLIST suite suiteDir CDATA #IMPLIED >\r
-\r
-   <!ELEMENT ajc-test (compile, (compile | inc-compile | run)*)>\r
+       <!-- permits leading inc-compile, will fail -->\r
+   <!ELEMENT ajc-test ((compile | inc-compile | run)*)>\r
    <!ATTLIST ajc-test title CDATA #REQUIRED >\r
    <!ATTLIST ajc-test dir CDATA #REQUIRED >\r
    <!ATTLIST ajc-test pr CDATA #IMPLIED >\r
@@ -42,6 +42,9 @@
    <!ATTLIST run fork CDATA #IMPLIED >\r
    <!ATTLIST run vmargs CDATA #IMPLIED >\r
    <!ATTLIST run aspectpath CDATA #IMPLIED >\r
+   <!ATTLIST run classpath CDATA #IMPLIED >\r
+   <!ATTLIST run LTW CDATA #IMPLIED >\r
+   <!ATTLIST run exception CDATA #IMPLIED >\r
 \r
    <!ELEMENT message (source*)>\r
    <!ATTLIST message kind (abort | fail | error | warning | info | Xlint) #REQUIRED >\r
diff --git a/tests/harness/fork/MainWriter.java b/tests/harness/fork/MainWriter.java
new file mode 100644 (file)
index 0000000..a7b3993
--- /dev/null
@@ -0,0 +1,14 @@
+
+public class MainWriter {
+    public static void main(String[] args) {
+        if (args.length > 0) {
+            if ("err".equals(args[0])) {
+                System.err.println("System.err");
+            } else if ("out".equals(args[0])) {
+                System.out.println("System.out");
+            } else if ("Error".equals(args[0])) {
+                throw new Error();
+            }
+        }
+    }
+}
\ No newline at end of file