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.
// 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,
}
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;
MessageUtil.abort(status, spec.testSetup.failureReason);
return false;
}
-// boolean ignoreWarnings =
-// (spec.testSetup.ignoreWarningsSet
-// && spec.testSetup.ignoreWarnings);
+
AjcMessageHandler handler =
new AjcMessageHandler(spec.getMessages());
handler.init();
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;
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.*;
* @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")
ClassNotFoundException,
NoSuchMethodException {
boolean completedNormally = false;
+ boolean passed = false;
if (!LangUtil.isEmpty(spec.dirChanges)) {
MessageUtil.info(status, "XXX dirChanges not implemented in JavaRun");
}
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);
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);
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) {
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;
}
/**
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 {
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();
class DoneFlag {
boolean done;
boolean failed;
+ int code;
}
final StringBuffer commandLabel = new StringBuffer();
final DoneFlag doneFlag = new DoneFlag();
+ 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;
// 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;
}
}
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;
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,
protected final ForkSpec forkSpec;
protected String[] aspectpath;
+ protected boolean useLTW;
+ protected String[] classpath;
+ protected String expectedException;
public Spec() {
super(XMLNAME);
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
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 */
/** cache results of rendering final fields */
private transient String toStringLeader;
+ private transient boolean compilerRunInit;
+
/** @throws IllegalArgumentException unless validator validates
* testBaseDir as readable
*/
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);
* 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");
* @param bootClasspath
* @param caller
*/
- void setBootclasspath(String bootClasspath, CompilerRun caller) {
+ private void setBootclasspath(String bootClasspath, CompilerRun caller) {
this.bootClasspath = bootClasspath;
}
* 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");
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;
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);
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
<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>
\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
<!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
--- /dev/null
+
+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