diff options
author | Andy Clement <aclement@pivotal.io> | 2019-11-29 11:36:58 -0800 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2019-11-29 11:36:58 -0800 |
commit | 17026e35243f229c2e3c07c292f2caaac65503a4 (patch) | |
tree | ac7d72940ca7c36e3358c8bf341a36d560741ef2 /testing-drivers | |
parent | c3c07fdb4b93cc483317d8a314233f0b9dcf4d8b (diff) | |
download | aspectj-17026e35243f229c2e3c07c292f2caaac65503a4.tar.gz aspectj-17026e35243f229c2e3c07c292f2caaac65503a4.zip |
polish
Diffstat (limited to 'testing-drivers')
-rw-r--r-- | testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java | 697 | ||||
-rw-r--r-- | testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java | 2413 |
2 files changed, 1571 insertions, 1539 deletions
diff --git a/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java b/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java index 05efb60e6..fea887cb6 100644 --- a/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java +++ b/testing-drivers/src/test/java/org/aspectj/testing/drivers/AjctestsAdapter.java @@ -1,12 +1,12 @@ /* ******************************************************************* * Copyright (c) 2003 Contributors - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: * Wes Isberg initial implementation * ******************************************************************/ @@ -18,17 +18,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestResult; -import junit.framework.TestSuite; - import org.aspectj.ajdt.internal.core.builder.AjState; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHolder; import org.aspectj.bridge.MessageHandler; import org.aspectj.bridge.MessageUtil; import org.aspectj.testing.harness.bridge.AjcTest; +import org.aspectj.testing.harness.bridge.AjcTest.Spec; import org.aspectj.testing.harness.bridge.RunSpecIterator; import org.aspectj.testing.harness.bridge.Sandbox; import org.aspectj.testing.harness.bridge.Validator; @@ -36,6 +32,11 @@ import org.aspectj.testing.run.IRunIterator; import org.aspectj.testing.run.RunStatus; import org.aspectj.testing.run.Runner; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestResult; +import junit.framework.TestSuite; + /* * Adapt Harness tests to JUnit driver. This renders suite files as TestSuite * and AjcTest as TestCase. When run, aborts are reported as error and fails as @@ -47,336 +48,344 @@ import org.aspectj.testing.run.Runner; * the test. */ public class AjctestsAdapter extends TestSuite { - public static final String VERBOSE_NAME = AjctestsAdapter.class.getName() - + ".VERBOSE"; - - private static final boolean VERBOSE = HarnessJUnitUtil - .readBooleanSystemProperty(VERBOSE_NAME); - - /** - * Factory to make and populate suite without options. - * - * @param suitePath - * the String path to a harness suite file - * @return AjctestJUnitSuite populated with tests - */ - public static AjctestsAdapter make(String suitePath) { - return make(suitePath, null); - } - - /** - * Factory to make and populate suite - * - * @param suitePath - * the String path to a harness suite file - * @param options - * the String[] options to use when creating tests - * @return AjctestJUnitSuite populated with tests - */ - public static AjctestsAdapter make(String suitePath, String[] options) { - AjctestsAdapter result = new AjctestsAdapter(suitePath, options); - AjcTest.Spec[] tests = AjcTest.Suite.getTests(result.getSpec()); - if (VERBOSE) { - log("loading " + tests.length + " tests in " + suitePath); - } - for (int i = 0; i < tests.length; i++) { - AjcTest.Spec ajcTest = tests[i]; - result.addTest(new AjcTestSpecAsTest(ajcTest, result)); - } - return result; - } - - private static void log(String message) { - System.err.println(message); - System.err.flush(); - } - - private final String suitePath; - - private final String[] options; - - private AjcTest.Suite.Spec spec; - - private Runner runner; - - private Validator validator; - - private IMessageHolder holder; - - private Sandbox sandbox; - - private File suiteDir; - - private String name; - - private AjctestsAdapter(String suitePath, String[] options) { - this.suitePath = suitePath; - String[] opts = new String[0]; - if (!HarnessJUnitUtil.isEmpty(options)) { - opts = new String[options.length]; - System.arraycopy(options, 0, opts, 0, opts.length); - } - this.options = opts; - } - - public void addTest(Test test) { - if (!(test instanceof AjcTestSpecAsTest)) { - String m = "expecting AjcTestSpecAsTest, got " - + (null == test ? "null test" : test.getClass().getName() - + ": " + test); - throw new IllegalArgumentException(m); - } - super.addTest(test); - } - - public void addTestSuite(Class testClass) { - throw new Error("unimplemented"); - } - - public String getName() { - if (null == name) { - name = HarnessJUnitUtil.cleanTestName(suitePath - + Arrays.asList(options)); - } - return name; - } - - /** - * Callback from test to run it using suite-wide holder, etc. The caller is - * responsible for calling result.startTest(test) and result.endTest(test); - * - * @param test - * the AjcTestSpecAsTest to run - * @param result - * the TestResult for any result messages (may be null) - */ - protected void runTest(AjcTestSpecAsTest test, TestResult result) { - final Runner runner = getRunner(); - final Sandbox sandbox = getSandbox(); - final Validator validator = getValidator(); - int numIncomplete = 0; - final RunStatus status = new RunStatus(new MessageHandler(), runner); - status.setIdentifier(test.toString()); - try { - IMessageHolder holder = getHolder(); - holder.clearMessages(); - IRunIterator steps = test.spec.makeRunIterator(sandbox, validator); - if (0 < holder.numMessages(IMessage.ERROR, true)) { - MessageUtil.handleAll(status, holder, IMessage.INFO, true, - false); - } else { - runner.runIterator(steps, status, null); - } - if (steps instanceof RunSpecIterator) { - numIncomplete = ((RunSpecIterator) steps).getNumIncomplete(); - } - } finally { - try { - // reportResult handles null TestResult - HarnessJUnitUtil - .reportResult(null, status, test, numIncomplete); - } finally { - validator.deleteTempFiles(true); - } - } - } - - private File getSuiteDir() { - if (null == suiteDir) { - File file = new File(suitePath); - file = file.getParentFile(); - if (null == file) { - file = new File("."); - } - suiteDir = file; - } - return suiteDir; - } - - private Validator getValidator() { - if (null == validator) { - validator = new Validator(getHolder()); - // XXX lock if keepTemp? - } - return validator; - } - - private Runner getRunner() { - if (null == runner) { - runner = new Runner(); - } - return runner; - } - - private IMessageHolder getHolder() { - if (null == holder) { - holder = new MessageHandler(); - } - return holder; - } - - private AjcTest.Suite.Spec getSpec() { - if (null == spec) { - IMessageHolder holder = getHolder(); - spec = HarnessJUnitUtil.getSuiteSpec(suitePath, options, - getHolder()); - if (VERBOSE && holder.hasAnyMessage(null, true)) { - MessageUtil.print(System.err, holder, "skip ", - MessageUtil.MESSAGE_MOST); - } - holder.clearMessages(); - } - return spec; - } - - private Sandbox getSandbox() { - if (null == sandbox) { - sandbox = new Sandbox(spec.getSuiteDirFile(), getValidator()); - } - return sandbox; - } - - /** - * Wrap AjcTest.Spec for lookup by description - * - * @author wes - */ - public static class SpecTests { - private static final HashMap TESTS = new HashMap(); - -// private static void putSpecTestsFor(String id, SpecTests tests) { -// TESTS.put(id, tests); -// } - - private static SpecTests getSpecTestsFor(String id) { - SpecTests result = (SpecTests) TESTS.get(id); - if (null == result) { - throw new Error("no tests found for " + id); - } - return result; - } - - // ------------------------------------ - final AjctestsAdapter mAjctestsAdapter; - - private final Map mDescriptionToAjcTestSpec; - - // ------------------------------------ - private SpecTests(AjctestsAdapter ajctestsAdapter, AjcTest.Spec[] tests) { - mAjctestsAdapter = ajctestsAdapter; - Map map = new HashMap(); - for (int i = 0; i < tests.length; i++) { - map.put(tests[i].getDescription(), tests[i]); - } - - mDescriptionToAjcTestSpec = Collections.unmodifiableMap(map); - } - - /** - * @param description - * the String description of the test - * @throws IllegalArgumentException - * if testName is not found - */ - protected void runTest(String description) { - AjcTest.Spec spec = getSpec(description); - AjctestsAdapter.AjcTestSpecAsTest ajcTestAsSpec = new AjctestsAdapter.AjcTestSpecAsTest( - spec, mAjctestsAdapter); - // runTest handles null TestResult - mAjctestsAdapter.runTest(ajcTestAsSpec, null); - } - - /** - * @param description - * the String description of the test - * @throws IllegalArgumentException - * if testName is not found - */ - private AjcTest.Spec getSpec(String description) { - AjcTest.Spec spec = (AjcTest.Spec) mDescriptionToAjcTestSpec - .get(description); - if (null == spec) { - throw new IllegalArgumentException("no test for " + description); - } - return spec; - } - - /** - * makeUsingTestClass(..) extends this to create TestCase with - * test_{name} for each test case. - */ - public static class TestClass extends TestCase { - public TestClass() { - } - private SpecTests mTests; - - /** - * Called by code generated in makeUsingTestClass(..) - * - * @param description - * the String identifier of the test stored in SpecTests - * mTests. - * @throws Error - * on first and later uses if getTestsFor() returns - * null. - */ - public final void runTest(String description) { - if (null == mTests) { - String classname = getClass().getName(); - mTests = getSpecTestsFor(classname); - } - mTests.runTest(description); - } - } - } - - /** Wrap AjcTest.Spec as a TestCase. Run by delegation to suite */ - private static class AjcTestSpecAsTest extends TestCase implements - HarnessJUnitUtil.IHasAjcSpec { - // this could implement Test, but Ant batchtest fails to pull name - final String name; - - final AjcTest.Spec spec; - - AjctestsAdapter suite; - - AjcTestSpecAsTest(AjcTest.Spec spec, AjctestsAdapter suite) { - super(HarnessJUnitUtil.cleanTestName(spec.getDescription())); - this.name = HarnessJUnitUtil.cleanTestName(spec.getDescription()); - this.suite = suite; - this.spec = spec; - spec.setSuiteDir(suite.getSuiteDir()); - } - - public int countTestCases() { - return 1; - } - - public AjcTest.Spec getAjcTestSpec() { - return spec; - } - - public void run(TestResult result) { - if (null == suite) { - throw new Error("need to re-init"); - } - try { - AjState.FORCE_INCREMENTAL_DURING_TESTING = true; - result.startTest(this); - suite.runTest(this, result); - } finally { - result.endTest(this); - suite = null; - AjState.FORCE_INCREMENTAL_DURING_TESTING = false; - } - } - - public String getName() { - return name; - } - - public String toString() { - return name; - } - } + public static final String VERBOSE_NAME = AjctestsAdapter.class.getName() + + ".VERBOSE"; + + private static final boolean VERBOSE = HarnessJUnitUtil + .readBooleanSystemProperty(VERBOSE_NAME); + + /** + * Factory to make and populate suite without options. + * + * @param suitePath + * the String path to a harness suite file + * @return AjctestJUnitSuite populated with tests + */ + public static AjctestsAdapter make(String suitePath) { + return make(suitePath, null); + } + + /** + * Factory to make and populate suite + * + * @param suitePath + * the String path to a harness suite file + * @param options + * the String[] options to use when creating tests + * @return AjctestJUnitSuite populated with tests + */ + public static AjctestsAdapter make(String suitePath, String[] options) { + AjctestsAdapter result = new AjctestsAdapter(suitePath, options); + AjcTest.Spec[] tests = AjcTest.Suite.getTests(result.getSpec()); + if (VERBOSE) { + log("loading " + tests.length + " tests in " + suitePath); + } + for (Spec ajcTest : tests) { + result.addTest(new AjcTestSpecAsTest(ajcTest, result)); + } + return result; + } + + private static void log(String message) { + System.err.println(message); + System.err.flush(); + } + + private final String suitePath; + + private final String[] options; + + private AjcTest.Suite.Spec spec; + + private Runner runner; + + private Validator validator; + + private IMessageHolder holder; + + private Sandbox sandbox; + + private File suiteDir; + + private String name; + + private AjctestsAdapter(String suitePath, String[] options) { + this.suitePath = suitePath; + String[] opts = new String[0]; + if (!HarnessJUnitUtil.isEmpty(options)) { + opts = new String[options.length]; + System.arraycopy(options, 0, opts, 0, opts.length); + } + this.options = opts; + } + + @Override + public void addTest(Test test) { + if (!(test instanceof AjcTestSpecAsTest)) { + String m = "expecting AjcTestSpecAsTest, got " + + (null == test ? "null test" : test.getClass().getName() + + ": " + test); + throw new IllegalArgumentException(m); + } + super.addTest(test); + } + + @SuppressWarnings("rawtypes") + @Override + public void addTestSuite(Class testClass) { + throw new Error("unimplemented"); + } + + @Override + public String getName() { + if (null == name) { + name = HarnessJUnitUtil.cleanTestName(suitePath + + Arrays.asList(options)); + } + return name; + } + + /** + * Callback from test to run it using suite-wide holder, etc. The caller is + * responsible for calling result.startTest(test) and result.endTest(test); + * + * @param test + * the AjcTestSpecAsTest to run + * @param result + * the TestResult for any result messages (may be null) + */ + protected void runTest(AjcTestSpecAsTest test, TestResult result) { + final Runner runner = getRunner(); + final Sandbox sandbox = getSandbox(); + final Validator validator = getValidator(); + int numIncomplete = 0; + final RunStatus status = new RunStatus(new MessageHandler(), runner); + status.setIdentifier(test.toString()); + try { + IMessageHolder holder = getHolder(); + holder.clearMessages(); + IRunIterator steps = test.spec.makeRunIterator(sandbox, validator); + if (0 < holder.numMessages(IMessage.ERROR, true)) { + MessageUtil.handleAll(status, holder, IMessage.INFO, true, + false); + } else { + runner.runIterator(steps, status, null); + } + if (steps instanceof RunSpecIterator) { + numIncomplete = ((RunSpecIterator) steps).getNumIncomplete(); + } + } finally { + try { + // reportResult handles null TestResult + HarnessJUnitUtil + .reportResult(null, status, test, numIncomplete); + } finally { + validator.deleteTempFiles(true); + } + } + } + + private File getSuiteDir() { + if (null == suiteDir) { + File file = new File(suitePath); + file = file.getParentFile(); + if (null == file) { + file = new File("."); + } + suiteDir = file; + } + return suiteDir; + } + + private Validator getValidator() { + if (null == validator) { + validator = new Validator(getHolder()); + // XXX lock if keepTemp? + } + return validator; + } + + private Runner getRunner() { + if (null == runner) { + runner = new Runner(); + } + return runner; + } + + private IMessageHolder getHolder() { + if (null == holder) { + holder = new MessageHandler(); + } + return holder; + } + + private AjcTest.Suite.Spec getSpec() { + if (null == spec) { + IMessageHolder holder = getHolder(); + spec = HarnessJUnitUtil.getSuiteSpec(suitePath, options, + getHolder()); + if (VERBOSE && holder.hasAnyMessage(null, true)) { + MessageUtil.print(System.err, holder, "skip ", + MessageUtil.MESSAGE_MOST); + } + holder.clearMessages(); + } + return spec; + } + + private Sandbox getSandbox() { + if (null == sandbox) { + sandbox = new Sandbox(spec.getSuiteDirFile(), getValidator()); + } + return sandbox; + } + + /** + * Wrap AjcTest.Spec for lookup by description + * + * @author wes + */ + public static class SpecTests { + private static final HashMap<String,SpecTests> TESTS = new HashMap<>(); + + // private static void putSpecTestsFor(String id, SpecTests tests) { + // TESTS.put(id, tests); + // } + + private static SpecTests getSpecTestsFor(String id) { + SpecTests result = TESTS.get(id); + if (null == result) { + throw new Error("no tests found for " + id); + } + return result; + } + + // ------------------------------------ + final AjctestsAdapter mAjctestsAdapter; + + private final Map<String,AjcTest.Spec> mDescriptionToAjcTestSpec; + + // ------------------------------------ + private SpecTests(AjctestsAdapter ajctestsAdapter, AjcTest.Spec[] tests) { + mAjctestsAdapter = ajctestsAdapter; + Map<String,AjcTest.Spec> map = new HashMap<>(); + for (Spec test : tests) { + map.put(test.getDescription(), test); + } + + mDescriptionToAjcTestSpec = Collections.unmodifiableMap(map); + } + + /** + * @param description + * the String description of the test + * @throws IllegalArgumentException + * if testName is not found + */ + protected void runTest(String description) { + AjcTest.Spec spec = getSpec(description); + AjctestsAdapter.AjcTestSpecAsTest ajcTestAsSpec = new AjctestsAdapter.AjcTestSpecAsTest( + spec, mAjctestsAdapter); + // runTest handles null TestResult + mAjctestsAdapter.runTest(ajcTestAsSpec, null); + } + + /** + * @param description + * the String description of the test + * @throws IllegalArgumentException + * if testName is not found + */ + private AjcTest.Spec getSpec(String description) { + AjcTest.Spec spec = mDescriptionToAjcTestSpec + .get(description); + if (null == spec) { + throw new IllegalArgumentException("no test for " + description); + } + return spec; + } + + /** + * makeUsingTestClass(..) extends this to create TestCase with + * test_{name} for each test case. + */ + public static class TestClass extends TestCase { + public TestClass() { + } + private SpecTests mTests; + + /** + * Called by code generated in makeUsingTestClass(..) + * + * @param description + * the String identifier of the test stored in SpecTests + * mTests. + * @throws Error + * on first and later uses if getTestsFor() returns + * null. + */ + public final void runTest(String description) { + if (null == mTests) { + String classname = getClass().getName(); + mTests = getSpecTestsFor(classname); + } + mTests.runTest(description); + } + } + } + + /** Wrap AjcTest.Spec as a TestCase. Run by delegation to suite */ + private static class AjcTestSpecAsTest extends TestCase implements + HarnessJUnitUtil.IHasAjcSpec { + // this could implement Test, but Ant batchtest fails to pull name + final String name; + + final AjcTest.Spec spec; + + AjctestsAdapter suite; + + AjcTestSpecAsTest(AjcTest.Spec spec, AjctestsAdapter suite) { + super(HarnessJUnitUtil.cleanTestName(spec.getDescription())); + this.name = HarnessJUnitUtil.cleanTestName(spec.getDescription()); + this.suite = suite; + this.spec = spec; + spec.setSuiteDir(suite.getSuiteDir()); + } + + @Override + public int countTestCases() { + return 1; + } + + @Override + public AjcTest.Spec getAjcTestSpec() { + return spec; + } + + @Override + public void run(TestResult result) { + if (null == suite) { + throw new Error("need to re-init"); + } + try { + AjState.FORCE_INCREMENTAL_DURING_TESTING = true; + result.startTest(this); + suite.runTest(this, result); + } finally { + result.endTest(this); + suite = null; + AjState.FORCE_INCREMENTAL_DURING_TESTING = false; + } + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + } }
\ No newline at end of file diff --git a/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java b/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java index 767444ce3..f1c8b3635 100644 --- a/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java +++ b/testing-drivers/src/test/java/org/aspectj/testing/drivers/Harness.java @@ -32,6 +32,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; @@ -44,6 +45,7 @@ import org.aspectj.testing.harness.bridge.AbstractRunSpec; import org.aspectj.testing.harness.bridge.AjcTest; import org.aspectj.testing.harness.bridge.CompilerRun; import org.aspectj.testing.harness.bridge.FlatSuiteReader; +import org.aspectj.testing.harness.bridge.IRunSpec; import org.aspectj.testing.harness.bridge.IncCompilerRun; import org.aspectj.testing.harness.bridge.JavaRun; import org.aspectj.testing.harness.bridge.RunSpecIterator; @@ -82,236 +84,236 @@ import org.aspectj.util.LangUtil; * categories. */ public class Harness { - /** - * Spaces up to the width that an option should take in the syntax, - * including the two-space leader - */ - protected static final String SYNTAX_PAD = " "; - protected static final String OPTION_DELIM = ";"; - private static final String JAVA_VERSION; - private static final String ASPECTJ_VERSION; - static { - String version = "UNKNOWN"; - try { version = System.getProperty("java.version", "UNKNOWN"); } - catch (Throwable t) {} - JAVA_VERSION = version; - - version = "UNKNOWN"; - try { - Class c = Class.forName("org.aspectj.bridge.Version"); - version = (String) c.getField("text").get(null); - } catch (Throwable t) { - // ignore - } - ASPECTJ_VERSION = version; - } - - /** factory for the subclass currently anointed as default */ - public static Harness makeHarness() { - return new FeatureHarness(); - } - - /** @param args String[] like runMain(String[]) args */ - public static void main(String[] args) throws Exception { - if (LangUtil.isEmpty(args)) { - File argFile = new File("HarnessArgs.txt"); - if (argFile.canRead()) { - args = readArgs(argFile); - } else { - args = new String[] { "-help" }; - } - } - makeHarness().runMain(args, null); - } - - /** - * Get known option aliases. - * Subclasses may add new aliases, where the key is the alias option, - * and the value is a comma-delimited String of target options. - * @return Properties with feature aliases or null - */ - protected static Properties getOptionAliases() { - if (null == optionAliases) { - optionAliases = new Properties(); - // XXX load from **OptionAliases.properties - } - return optionAliases; - } - - /** - * Read argFile contents into String[], - * delimiting at any whitespace - */ - private static String[] readArgs(File argFile) { - ArrayList<String> args = new ArrayList<>(); -// int lineNum = 0; - - try { - BufferedReader stream = - new BufferedReader(new FileReader(argFile)); - String line; - while (null != (line = stream.readLine())) { - StringTokenizer st = new StringTokenizer(line); - while (st.hasMoreTokens()) { - args.add(st.nextToken()); - } - } - } catch (IOException e) { - e.printStackTrace(System.err); - } - return args.toArray(new String[0]); - } - - /** aliases key="option" value="option{,option}" */ - private static Properties optionAliases; - - /** be extra noisy if true */ - private boolean verboseHarness; - - /** be extra quiet if true */ - private boolean quietHarness; - - /** just don't say anything! */ - protected boolean silentHarness; - - private HashMap<String,Feature> features; + /** + * Spaces up to the width that an option should take in the syntax, + * including the two-space leader + */ + protected static final String SYNTAX_PAD = " "; + protected static final String OPTION_DELIM = ";"; + private static final String JAVA_VERSION; + private static final String ASPECTJ_VERSION; + static { + String version = "UNKNOWN"; + try { version = System.getProperty("java.version", "UNKNOWN"); } + catch (Throwable t) {} + JAVA_VERSION = version; + + version = "UNKNOWN"; + try { + Class c = Class.forName("org.aspectj.bridge.Version"); + version = (String) c.getField("text").get(null); + } catch (Throwable t) { + // ignore + } + ASPECTJ_VERSION = version; + } + + /** factory for the subclass currently anointed as default */ + public static Harness makeHarness() { + return new FeatureHarness(); + } + + /** @param args String[] like runMain(String[]) args */ + public static void main(String[] args) throws Exception { + if (LangUtil.isEmpty(args)) { + File argFile = new File("HarnessArgs.txt"); + if (argFile.canRead()) { + args = readArgs(argFile); + } else { + args = new String[] { "-help" }; + } + } + makeHarness().runMain(args, null); + } + + /** + * Get known option aliases. + * Subclasses may add new aliases, where the key is the alias option, + * and the value is a comma-delimited String of target options. + * @return Properties with feature aliases or null + */ + protected static Properties getOptionAliases() { + if (null == optionAliases) { + optionAliases = new Properties(); + // XXX load from **OptionAliases.properties + } + return optionAliases; + } + + /** + * Read argFile contents into String[], + * delimiting at any whitespace + */ + private static String[] readArgs(File argFile) { + ArrayList<String> args = new ArrayList<>(); + // int lineNum = 0; + + try { + BufferedReader stream = + new BufferedReader(new FileReader(argFile)); + String line; + while (null != (line = stream.readLine())) { + StringTokenizer st = new StringTokenizer(line); + while (st.hasMoreTokens()) { + args.add(st.nextToken()); + } + } + } catch (IOException e) { + e.printStackTrace(System.err); + } + return args.toArray(new String[0]); + } + + /** aliases key="option" value="option{,option}" */ + private static Properties optionAliases; + + /** be extra noisy if true */ + private boolean verboseHarness; + + /** be extra quiet if true */ + private boolean quietHarness; + + /** just don't say anything! */ + protected boolean silentHarness; + + private HashMap<String,Feature> features; /** if true, do not delete temporary files. */ private boolean keepTemp; - /** if true, delete temporary files as each test completes. */ - private boolean killTemp; + /** if true, delete temporary files as each test completes. */ + private boolean killTemp; /** if true, then log results in report(..) when done */ private boolean logResults; - /** if true and there were failures, do System.exit({numFailures})*/ - private boolean exitOnFailure; - - protected Harness() { - features = new HashMap<>(); - } - - - /** - * Entry point for a test. - * This reads in the arguments, - * creates the test suite(s) from the input file(s), - * and for each suite does setup, run, report, and cleanup. - * When arguments are read, any option ending with "-" causes - * option variants, a set of args with and another without the - * option. See {@link LangUtil.optionVariants(String[])} for - * more details. - * @param args the String[] for the test suite - use -help to get options, - * and use "-" suffixes for variants. - * @param resultList List for IRunStatus results - ignored if null - */ - public void runMain(String[] args, List resultList) { - LangUtil.throwIaxIfFalse(!LangUtil.isEmpty(args), "empty args"); - // read arguments - final ArrayList<String> globals = new ArrayList<>(); - final ArrayList<String> files = new ArrayList<>(); - final LinkedList<String> argList = new LinkedList<>(); - argList.addAll(Arrays.asList(args)); - for (int i = 0; i < argList.size(); i++) { - String arg = argList.get(i); - List<String> aliases = aliasOptions(arg); - if (!LangUtil.isEmpty(aliases)) { - argList.remove(i); - argList.addAll(i, aliases); - i--; - continue; - } - if ("-help".equals(arg)) { - logln("java " + Harness.class.getName() + " {option|suiteFile}.."); - printSyntax(getLogStream()); - return; - } else if (isSuiteFile(arg)) { - files.add(arg); - } else if (!acceptOption(arg)) { - globals.add(arg); - } // else our options absorbed - } - if (0 == files.size()) { - logln("## Error reading arguments: at least 1 suite file required"); - logln("java " + Harness.class.getName() + " {option|suiteFile}.."); - printSyntax(getLogStream()); - return; - } - String[] globalOptions = globals.toArray(new String[0]); - String[][] globalOptionVariants = optionVariants(globalOptions); - AbstractRunSpec.RT runtime = new AbstractRunSpec.RT(); - if (verboseHarness) { - runtime.setVerbose(true); - } - - // run suites read from each file - AjcTest.Suite.Spec spec; - for (Iterator iter = files.iterator(); iter.hasNext();) { - File suiteFile = new File((String) iter.next()); - if (!suiteFile.canRead()) { - logln("runMain(..) cannot read file: " + suiteFile); - continue; - } - if (null == (spec = readSuite(suiteFile))) { - logln("runMain(..) cannot read suite from file: " + suiteFile); - continue; - } - - MessageHandler holder = new MessageHandler(); - for (int i = 0; i < globalOptionVariants.length; i++) { - runtime.setOptions(globalOptionVariants[i]); - holder.init(); - boolean skip = !spec.adoptParentValues(runtime, holder); - // awful/brittle assumption about number of skips == number of skip messages - final List skipList = MessageUtil.getMessages(holder, IMessage.INFO, false, "skip"); - if ((verboseHarness || skip || (0 < skipList.size()))) { - final List curArgs = Arrays.asList(globalOptionVariants[i]); + /** if true and there were failures, do System.exit({numFailures})*/ + private boolean exitOnFailure; + + protected Harness() { + features = new HashMap<>(); + } + + + /** + * Entry point for a test. + * This reads in the arguments, + * creates the test suite(s) from the input file(s), + * and for each suite does setup, run, report, and cleanup. + * When arguments are read, any option ending with "-" causes + * option variants, a set of args with and another without the + * option. See {@link LangUtil.optionVariants(String[])} for + * more details. + * @param args the String[] for the test suite - use -help to get options, + * and use "-" suffixes for variants. + * @param resultList List for IRunStatus results - ignored if null + */ + public void runMain(String[] args, List resultList) { + LangUtil.throwIaxIfFalse(!LangUtil.isEmpty(args), "empty args"); + // read arguments + final ArrayList<String> globals = new ArrayList<>(); + final ArrayList<String> files = new ArrayList<>(); + final LinkedList<String> argList = new LinkedList<>(); + argList.addAll(Arrays.asList(args)); + for (int i = 0; i < argList.size(); i++) { + String arg = argList.get(i); + List<String> aliases = aliasOptions(arg); + if (!LangUtil.isEmpty(aliases)) { + argList.remove(i); + argList.addAll(i, aliases); + i--; + continue; + } + if ("-help".equals(arg)) { + logln("java " + Harness.class.getName() + " {option|suiteFile}.."); + printSyntax(getLogStream()); + return; + } else if (isSuiteFile(arg)) { + files.add(arg); + } else if (!acceptOption(arg)) { + globals.add(arg); + } // else our options absorbed + } + if (0 == files.size()) { + logln("## Error reading arguments: at least 1 suite file required"); + logln("java " + Harness.class.getName() + " {option|suiteFile}.."); + printSyntax(getLogStream()); + return; + } + String[] globalOptions = globals.toArray(new String[0]); + String[][] globalOptionVariants = optionVariants(globalOptions); + AbstractRunSpec.RT runtime = new AbstractRunSpec.RT(); + if (verboseHarness) { + runtime.setVerbose(true); + } + + // run suites read from each file + AjcTest.Suite.Spec spec; + for (String string : files) { + File suiteFile = new File(string); + if (!suiteFile.canRead()) { + logln("runMain(..) cannot read file: " + suiteFile); + continue; + } + if (null == (spec = readSuite(suiteFile))) { + logln("runMain(..) cannot read suite from file: " + suiteFile); + continue; + } + + MessageHandler holder = new MessageHandler(); + for (String[] globalOptionVariant : globalOptionVariants) { + runtime.setOptions(globalOptionVariant); + holder.init(); + boolean skip = !spec.adoptParentValues(runtime, holder); + // awful/brittle assumption about number of skips == number of skip messages + final List<IMessage> skipList = MessageUtil.getMessages(holder, IMessage.INFO, false, "skip"); + if ((verboseHarness || skip || (0 < skipList.size()))) { + final List<String> curArgs = Arrays.asList(globalOptionVariant); logln("runMain(" + suiteFile + ", " + curArgs + ")"); - if (verboseHarness) { - String format = "yyyy.MM.dd G 'at' hh:mm:ss a zzz"; - SimpleDateFormat formatter = new SimpleDateFormat (format); - String date = formatter.format(new Date()); - logln("test date: " + date); - logln("harness features: " + listFeatureNames()); - logln("Java version: " + JAVA_VERSION); - logln("AspectJ version: " + ASPECTJ_VERSION); - } - if (!(quietHarness || silentHarness) && holder.hasAnyMessage(null, true)) { - MessageUtil.print(getLogStream(), holder, "skip - "); - MessageUtil.printMessageCounts(getLogStream(), holder, "skip - "); - } - } - if (!skip) { - doStartSuite(suiteFile); - long elapsed = 0; - RunResult result = null; - try { - final long startTime = System.currentTimeMillis(); - result = run(spec); - if (null != resultList) { - resultList.add(result); - } - elapsed = System.currentTimeMillis() - startTime; - report(result.status, skipList.size(), result.numIncomplete, elapsed); - } finally { - doEndSuite(suiteFile,elapsed); - } - if (exitOnFailure) { - int numFailures = RunUtils.numFailures(result.status, true); - if (0 < numFailures) { - System.exit(numFailures); - } - Object value = result.status.getResult(); - if ((value instanceof Boolean) - && !((Boolean) value).booleanValue()) { - System.exit(-1); - } - } - } - } - } - } + if (verboseHarness) { + String format = "yyyy.MM.dd G 'at' hh:mm:ss a zzz"; + SimpleDateFormat formatter = new SimpleDateFormat (format); + String date = formatter.format(new Date()); + logln("test date: " + date); + logln("harness features: " + listFeatureNames()); + logln("Java version: " + JAVA_VERSION); + logln("AspectJ version: " + ASPECTJ_VERSION); + } + if (!(quietHarness || silentHarness) && holder.hasAnyMessage(null, true)) { + MessageUtil.print(getLogStream(), holder, "skip - "); + MessageUtil.printMessageCounts(getLogStream(), holder, "skip - "); + } + } + if (!skip) { + doStartSuite(suiteFile); + long elapsed = 0; + RunResult result = null; + try { + final long startTime = System.currentTimeMillis(); + result = run(spec); + if (null != resultList) { + resultList.add(result); + } + elapsed = System.currentTimeMillis() - startTime; + report(result.status, skipList.size(), result.numIncomplete, elapsed); + } finally { + doEndSuite(suiteFile,elapsed); + } + if (exitOnFailure) { + int numFailures = RunUtils.numFailures(result.status, true); + if (0 < numFailures) { + System.exit(numFailures); + } + Object value = result.status.getResult(); + if ((value instanceof Boolean) + && !((Boolean) value).booleanValue()) { + System.exit(-1); + } + } + } + } + } + } /** @@ -328,72 +330,71 @@ public class Harness { } } } - /** - * Generate variants of String[] options by creating an extra set for - * each option that ends with "-". If none end with "-", then an - * array equal to <code>new String[][] { options }</code> is returned; - * if one ends with "-", then two sets are returned, - * three causes eight sets, etc. - * @return String[][] with each option set. - * @throws IllegalArgumentException if any option is null or empty. - */ - public static String[][] optionVariants(String[] options) { - if ((null == options) || (0 == options.length)) { - return new String[][] { new String[0]}; - } - // be nice, don't stomp input - String[] temp = new String[options.length]; - System.arraycopy(options, 0, temp, 0, temp.length); - options = temp; - boolean[] dup = new boolean[options.length]; - int numDups = 0; - - for (int i = 0; i < options.length; i++) { - String option = options[i]; - if (LangUtil.isEmpty(option)) { - throw new IllegalArgumentException("empty option at " + i); - } - if (option.endsWith("-")) { - options[i] = option.substring(0, option.length()-1); - dup[i] = true; - numDups++; - } - } - final String[] NONE = new String[0]; - final int variants = exp(2, numDups); - final String[][] result = new String[variants][]; - // variant is a bitmap wrt doing extra value when dup[k]=true - for (int variant = 0; variant < variants; variant++) { - ArrayList<String> next = new ArrayList<>(); - int nextOption = 0; - for (int k = 0; k < options.length; k++) { - if (!dup[k] || (0 != (variant & (1 << (nextOption++))))) { - next.add(options[k]); - } - } - result[variant] = next.toArray(NONE); - } - return result; - } - - private static int exp(int base, int power) { // not in Math? - if (0 > power) { - throw new IllegalArgumentException("negative power: " + power); - } - int result = 1; - while (0 < power--) { - result *= base; - } - return result; - } + /** + * Generate variants of String[] options by creating an extra set for + * each option that ends with "-". If none end with "-", then an + * array equal to <code>new String[][] { options }</code> is returned; + * if one ends with "-", then two sets are returned, + * three causes eight sets, etc. + * @return String[][] with each option set. + * @throws IllegalArgumentException if any option is null or empty. + */ + public static String[][] optionVariants(String[] options) { + if ((null == options) || (0 == options.length)) { + return new String[][] { new String[0]}; + } + // be nice, don't stomp input + String[] temp = new String[options.length]; + System.arraycopy(options, 0, temp, 0, temp.length); + options = temp; + boolean[] dup = new boolean[options.length]; + int numDups = 0; + + for (int i = 0; i < options.length; i++) { + String option = options[i]; + if (LangUtil.isEmpty(option)) { + throw new IllegalArgumentException("empty option at " + i); + } + if (option.endsWith("-")) { + options[i] = option.substring(0, option.length()-1); + dup[i] = true; + numDups++; + } + } + final String[] NONE = new String[0]; + final int variants = exp(2, numDups); + final String[][] result = new String[variants][]; + // variant is a bitmap wrt doing extra value when dup[k]=true + for (int variant = 0; variant < variants; variant++) { + ArrayList<String> next = new ArrayList<>(); + int nextOption = 0; + for (int k = 0; k < options.length; k++) { + if (!dup[k] || (0 != (variant & (1 << (nextOption++))))) { + next.add(options[k]); + } + } + result[variant] = next.toArray(NONE); + } + return result; + } + + private static int exp(int base, int power) { // not in Math? + if (0 > power) { + throw new IllegalArgumentException("negative power: " + power); + } + int result = 1; + while (0 < power--) { + result *= base; + } + return result; + } /** * @param suiteFile */ private void doStartSuite(File suiteFile) { - Collection c = features.values(); - for (Iterator iter = c.iterator(); iter.hasNext();) { - Feature element = (Feature) iter.next(); + Collection<Feature> c = features.values(); + for (Feature element : c) { if (element.listener instanceof TestCompleteListener) { ((TestCompleteListener)element.listener).doStartSuite(suiteFile); } @@ -401,271 +402,271 @@ public class Harness { } /** Run the test suite specified by the spec */ - protected RunResult run(AjcTest.Suite.Spec spec) { - LangUtil.throwIaxIfNull(spec, "spec"); - /* - * For each run, initialize the runner and validator, - * create a new set of IRun{Iterator} tests, - * and run them. - * Delete all temp files when done. - */ - Runner runner = new Runner(); - if (0 != features.size()) { - for (Iterator<Map.Entry<String,Feature>> iter = features.entrySet().iterator(); iter.hasNext();) { - Feature feature = iter.next().getValue(); - runner.registerListener(feature.clazz, feature.listener); - } - } - IMessageHolder holder = new MessageHandler(); - int numIncomplete = 0; - RunStatus status = new RunStatus(holder, runner); - status.setIdentifier(spec); - // validator is used for all setup in entire tree... - Validator validator = new Validator(status); - if (!killTemp) { - validator.lock(this); - } - Sandbox sandbox = null; - try { - sandbox = new Sandbox(spec.getSuiteDirFile(), validator); - IRunIterator tests = spec.makeRunIterator(sandbox, validator); - runner.runIterator(tests, status, null); - if (tests instanceof RunSpecIterator) { - numIncomplete = ((RunSpecIterator) tests).getNumIncomplete(); - } - } finally { - if (!keepTemp) { - if (!killTemp) { - validator.unlock(this); - } - validator.deleteTempFiles(verboseHarness); - } - } - return new RunResult(status, numIncomplete); - } - - /** - * Report the results of a test run after it is completed. - * Clients should be able to identify the number of: - * <ul> - * <li>tests run and passed</li> - * <li>tests failed, i.e., run and not passed (fail, error, etc.)</li> - * <li>tests incomplete, i.e., test definition read but test run setup failed</li> - * <li>tests skipped, i.e., test definition read and found incompatible with - * the current configuration.</li> - * <ul> - * - * @param status returned from the run - * @param numSkipped int tests that were skipped because of - * configuration incompatibilities - * @param numIncomplete int tests that failed during setup, - * usually indicating a test definition or configuration error. - * @param msElapsed elapsed time in milliseconds - * */ - protected void report(IRunStatus status, int numSkipped, int numIncomplete, - long msElapsed ) { - if (logResults) { - RunUtils.AJCSUITE_PRINTER.printRunStatus(getLogStream(), status); - } else if (!(quietHarness || silentHarness) && (0 < status.numMessages(null, true))) { - if (!silentHarness) { - MessageUtil.print(getLogStream(), status, ""); - } - } - - logln(BridgeUtil.childString(status, numSkipped, numIncomplete) - + " " + (msElapsed/1000) + " seconds"); - - } - - // --------------- delegate methods - protected void logln(String s) { - if (!silentHarness) { - getLogStream().println(s); - } - } - - protected PrintStream getLogStream() { - return System.out; - } - - protected boolean isSuiteFile(String arg) { - return ((null != arg) - && (arg.endsWith(".txt") || arg.endsWith(".xml")) - && new File(arg).canRead()); - } - - /** - * Get the options that the input option is an alias for. - * Subclasses may add options directly to the getFeatureAliases result - * or override this. - * @return null if the input is not an alias for other options, - * or a non-empty List (String) of options that this option is an alias for - */ - protected List<String> aliasOptions(String option) { - Properties aliases = Harness.getOptionAliases(); - if (null != aliases) { - String args = aliases.getProperty(option); - if (!LangUtil.isEmpty(args)) { - return LangUtil.anySplit(args, OPTION_DELIM); - } - } - return null; - } - - /** - * Read and implement any of our options. - * Options other than this and suite files will be - * passed down as parent options through the test spec hierarchy. - * Subclasses override this to implement new options. - */ - protected boolean acceptOption(String option) { -// boolean result = false; - if (LangUtil.isEmpty(option)) { - return true; // skip bad input - } else if ("-verboseHarness".equals(option)) { - verboseHarness = true; + protected RunResult run(AjcTest.Suite.Spec spec) { + LangUtil.throwIaxIfNull(spec, "spec"); + /* + * For each run, initialize the runner and validator, + * create a new set of IRun{Iterator} tests, + * and run them. + * Delete all temp files when done. + */ + Runner runner = new Runner(); + if (0 != features.size()) { + for (Entry<String, Feature> entry : features.entrySet()) { + Feature feature = entry.getValue(); + runner.registerListener(feature.clazz, feature.listener); + } + } + IMessageHolder holder = new MessageHandler(); + int numIncomplete = 0; + RunStatus status = new RunStatus(holder, runner); + status.setIdentifier(spec); + // validator is used for all setup in entire tree... + Validator validator = new Validator(status); + if (!killTemp) { + validator.lock(this); + } + Sandbox sandbox = null; + try { + sandbox = new Sandbox(spec.getSuiteDirFile(), validator); + IRunIterator tests = spec.makeRunIterator(sandbox, validator); + runner.runIterator(tests, status, null); + if (tests instanceof RunSpecIterator) { + numIncomplete = ((RunSpecIterator) tests).getNumIncomplete(); + } + } finally { + if (!keepTemp) { + if (!killTemp) { + validator.unlock(this); + } + validator.deleteTempFiles(verboseHarness); + } + } + return new RunResult(status, numIncomplete); + } + + /** + * Report the results of a test run after it is completed. + * Clients should be able to identify the number of: + * <ul> + * <li>tests run and passed</li> + * <li>tests failed, i.e., run and not passed (fail, error, etc.)</li> + * <li>tests incomplete, i.e., test definition read but test run setup failed</li> + * <li>tests skipped, i.e., test definition read and found incompatible with + * the current configuration.</li> + * <ul> + * + * @param status returned from the run + * @param numSkipped int tests that were skipped because of + * configuration incompatibilities + * @param numIncomplete int tests that failed during setup, + * usually indicating a test definition or configuration error. + * @param msElapsed elapsed time in milliseconds + * */ + protected void report(IRunStatus status, int numSkipped, int numIncomplete, + long msElapsed ) { + if (logResults) { + RunUtils.AJCSUITE_PRINTER.printRunStatus(getLogStream(), status); + } else if (!(quietHarness || silentHarness) && (0 < status.numMessages(null, true))) { + if (!silentHarness) { + MessageUtil.print(getLogStream(), status, ""); + } + } + + logln(BridgeUtil.childString(status, numSkipped, numIncomplete) + + " " + (msElapsed/1000) + " seconds"); + + } + + // --------------- delegate methods + protected void logln(String s) { + if (!silentHarness) { + getLogStream().println(s); + } + } + + protected PrintStream getLogStream() { + return System.out; + } + + protected boolean isSuiteFile(String arg) { + return ((null != arg) + && (arg.endsWith(".txt") || arg.endsWith(".xml")) + && new File(arg).canRead()); + } + + /** + * Get the options that the input option is an alias for. + * Subclasses may add options directly to the getFeatureAliases result + * or override this. + * @return null if the input is not an alias for other options, + * or a non-empty List (String) of options that this option is an alias for + */ + protected List<String> aliasOptions(String option) { + Properties aliases = Harness.getOptionAliases(); + if (null != aliases) { + String args = aliases.getProperty(option); + if (!LangUtil.isEmpty(args)) { + return LangUtil.anySplit(args, OPTION_DELIM); + } + } + return null; + } + + /** + * Read and implement any of our options. + * Options other than this and suite files will be + * passed down as parent options through the test spec hierarchy. + * Subclasses override this to implement new options. + */ + protected boolean acceptOption(String option) { + // boolean result = false; + if (LangUtil.isEmpty(option)) { + return true; // skip bad input + } else if ("-verboseHarness".equals(option)) { + verboseHarness = true; } else if ("-quietHarness".equals(option)) { quietHarness = true; } else if ("-silentHarness".equals(option)) { silentHarness = true; - } else if ("-keepTemp".equals(option)) { - keepTemp = true; - } else if ("-killTemp".equals(option)) { - killTemp = true; - } else if ("-logResults".equals(option)) { - logResults = true; - } else if ("-exitOnFailure".equals(option)) { - exitOnFailure = true; - } else { - return false; - } - return true; - } - - /** - * Read a test suite file. - * This implementation knows how to read .txt and .xml files - * and logs any errors. - * Subclasses override this to read new kinds of suites. - * @return null if unable to read (logging errors) or AjcTest.Suite.Spec otherwise - */ - protected AjcTest.Suite.Spec readSuite(File suiteFile) { - if (null != suiteFile) { - String path = suiteFile.getPath(); - try { - if (path.endsWith(".xml")) { - return AjcSpecXmlReader.getReader().readAjcSuite(suiteFile); - } else if (path.endsWith(".txt")) { - return FlatSuiteReader.ME.readSuite(suiteFile); - } else { - logln("unrecognized extension? " + path); - } - } catch (IOException e) { - e.printStackTrace(getLogStream()); - } - } - return null; - } - - /** Add feature to take effect during the next runMain(..) invocation. - * @param feature the Feature to add, using feature.name as key. - */ - protected void addFeature(Feature feature) { - if (null != feature) { - features.put(feature.name, feature); - } - } - - /** remove feature by name (same as feature.name) */ - protected void removeFeature(String name) { - if (!LangUtil.isEmpty(name)) { - features.remove(name); - } - } - - /** @return unmodifiable Set of feature names */ - protected Set listFeatureNames() { - return Collections.unmodifiableSet(features.keySet()); - } - - /** print detail message for syntax of main(String[]) command-line */ - protected void printSyntax(PrintStream out) { - out.println(" {??} unrecognized options are used as test spec globals"); - out.println(" -help print this help message"); - out.println(" -verboseHarness harness components log verbosely"); - out.println(" -quietHarness harness components suppress logging"); - out.println(" -keepTemp do not delete temporary files"); - out.println(" -logResults log results at end, verbosely if fail"); - out.println(" -exitOnFailure do System.exit({num-failures}) if suite fails"); - out.println(" {suiteFile}.xml.. specify test suite XML file"); - out.println(" {suiteFile}.txt.. specify test suite .txt file (deprecated)"); - } - - /** print known aliases at the end of the syntax message */ - protected void printAliases(PrintStream out) { - LangUtil.throwIaxIfNull(out, "out"); - Properties props = getOptionAliases(); - if (null == props) { - return; - } - int pdLength = SYNTAX_PAD.length(); - Set entries = props.entrySet(); - for (Iterator iter = entries.iterator(); iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); + } else if ("-keepTemp".equals(option)) { + keepTemp = true; + } else if ("-killTemp".equals(option)) { + killTemp = true; + } else if ("-logResults".equals(option)) { + logResults = true; + } else if ("-exitOnFailure".equals(option)) { + exitOnFailure = true; + } else { + return false; + } + return true; + } + + /** + * Read a test suite file. + * This implementation knows how to read .txt and .xml files + * and logs any errors. + * Subclasses override this to read new kinds of suites. + * @return null if unable to read (logging errors) or AjcTest.Suite.Spec otherwise + */ + protected AjcTest.Suite.Spec readSuite(File suiteFile) { + if (null != suiteFile) { + String path = suiteFile.getPath(); + try { + if (path.endsWith(".xml")) { + return AjcSpecXmlReader.getReader().readAjcSuite(suiteFile); + } else if (path.endsWith(".txt")) { + return FlatSuiteReader.ME.readSuite(suiteFile); + } else { + logln("unrecognized extension? " + path); + } + } catch (IOException e) { + e.printStackTrace(getLogStream()); + } + } + return null; + } + + /** Add feature to take effect during the next runMain(..) invocation. + * @param feature the Feature to add, using feature.name as key. + */ + protected void addFeature(Feature feature) { + if (null != feature) { + features.put(feature.name, feature); + } + } + + /** remove feature by name (same as feature.name) */ + protected void removeFeature(String name) { + if (!LangUtil.isEmpty(name)) { + features.remove(name); + } + } + + /** @return unmodifiable Set of feature names */ + protected Set listFeatureNames() { + return Collections.unmodifiableSet(features.keySet()); + } + + /** print detail message for syntax of main(String[]) command-line */ + protected void printSyntax(PrintStream out) { + out.println(" {??} unrecognized options are used as test spec globals"); + out.println(" -help print this help message"); + out.println(" -verboseHarness harness components log verbosely"); + out.println(" -quietHarness harness components suppress logging"); + out.println(" -keepTemp do not delete temporary files"); + out.println(" -logResults log results at end, verbosely if fail"); + out.println(" -exitOnFailure do System.exit({num-failures}) if suite fails"); + out.println(" {suiteFile}.xml.. specify test suite XML file"); + out.println(" {suiteFile}.txt.. specify test suite .txt file (deprecated)"); + } + + /** print known aliases at the end of the syntax message */ + protected void printAliases(PrintStream out) { + LangUtil.throwIaxIfNull(out, "out"); + Properties props = getOptionAliases(); + if (null == props) { + return; + } + int pdLength = SYNTAX_PAD.length(); + Set<Map.Entry<Object,Object>> entries = props.entrySet(); + for (Map.Entry<Object,Object> entry : entries) { String alias = " " + (String) entry.getKey(); - int buf = pdLength - alias.length(); - if (0 < buf) { - alias += SYNTAX_PAD.substring(0, buf); - } else { - alias += " "; - } - out.println(alias + entry.getValue()); - } - } - - /** result struct for run(AjcTest.Spec) */ - public static class RunResult { - public final IRunStatus status; - public final int numIncomplete; - public RunResult(IRunStatus status, int numIncomplete) { - this.status = status; - this.numIncomplete = numIncomplete; - } - } - /** feature implemented as named IRunIterator/IRun association */ - public static class Feature { - /** never null, always assignable to IRun */ - public final Class clazz; - - /** never null */ - public final IRunListener listener; - - /** never null or empty */ - public final String name; - - /** @throws IllegalArgumentException if any is null/empty or clazz is - * not assignable to IRun - */ - public Feature(String name, Class clazz, IRunListener listener) { - LangUtil.throwIaxIfNull(clazz, "class"); - if (!IRun.class.isAssignableFrom(clazz) - && !IRunIterator.class.isAssignableFrom(clazz)) { - String s = clazz.getName() + "is not assignable to IRun or IRunIterator"; - LangUtil.throwIaxIfFalse(false, s); - } - LangUtil.throwIaxIfNull(listener, "listener"); - LangUtil.throwIaxIfNull(name, "name"); - LangUtil.throwIaxIfFalse(0 < name.length(), "empty name"); - this.clazz = clazz; - this.listener = listener; - this.name = name; - } - - /** @return feature name */ - public String toString() { - return name; - } - } + int buf = pdLength - alias.length(); + if (0 < buf) { + alias += SYNTAX_PAD.substring(0, buf); + } else { + alias += " "; + } + out.println(alias + entry.getValue()); + } + } + + /** result struct for run(AjcTest.Spec) */ + public static class RunResult { + public final IRunStatus status; + public final int numIncomplete; + public RunResult(IRunStatus status, int numIncomplete) { + this.status = status; + this.numIncomplete = numIncomplete; + } + } + /** feature implemented as named IRunIterator/IRun association */ + public static class Feature { + /** never null, always assignable to IRun */ + public final Class clazz; + + /** never null */ + public final IRunListener listener; + + /** never null or empty */ + public final String name; + + /** @throws IllegalArgumentException if any is null/empty or clazz is + * not assignable to IRun + */ + public Feature(String name, Class clazz, IRunListener listener) { + LangUtil.throwIaxIfNull(clazz, "class"); + if (!IRun.class.isAssignableFrom(clazz) + && !IRunIterator.class.isAssignableFrom(clazz)) { + String s = clazz.getName() + "is not assignable to IRun or IRunIterator"; + LangUtil.throwIaxIfFalse(false, s); + } + LangUtil.throwIaxIfNull(listener, "listener"); + LangUtil.throwIaxIfNull(name, "name"); + LangUtil.throwIaxIfFalse(0 < name.length(), "empty name"); + this.clazz = clazz; + this.listener = listener; + this.name = name; + } + + /** @return feature name */ + @Override + public String toString() { + return name; + } + } } @@ -676,323 +677,333 @@ public class Harness { */ class FeatureHarness extends Harness { - private static final String[] ALIASES = new String[] - { "-hideStreams", - "-hideCompilerStreams" - + OPTION_DELIM + "-hideRunStreams", - "-jim", - "-logMinFail" - + OPTION_DELIM + "-hideStreams", - "-loud", - "-verboseHarness", - "-baseline", - "-verboseHarness" - + OPTION_DELIM + "-traceTestsMin" - + OPTION_DELIM + "-hideStreams", - "-release", - "-baseline" - + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava", - "-junit", - "-silentHarness" + OPTION_DELIM + "-logJUnit" + OPTION_DELIM + - "-hideStreams", - "-cruisecontrol", - "-junit" + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava" - }; - static { - Properties optionAliases = Harness.getOptionAliases(); - if (null != optionAliases) { - for (int i = 1; i < ALIASES.length; i += 2) { - optionAliases.put(ALIASES[i-1], ALIASES[i]); + private static final String[] ALIASES = new String[] + { "-hideStreams", + "-hideCompilerStreams" + + OPTION_DELIM + "-hideRunStreams", + "-jim", + "-logMinFail" + + OPTION_DELIM + "-hideStreams", + "-loud", + "-verboseHarness", + "-baseline", + "-verboseHarness" + + OPTION_DELIM + "-traceTestsMin" + + OPTION_DELIM + "-hideStreams", + "-release", + "-baseline" + + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava", + "-junit", + "-silentHarness" + OPTION_DELIM + "-logJUnit" + OPTION_DELIM + + "-hideStreams", + "-cruisecontrol", + "-junit" + OPTION_DELIM + "-ajctestSkipKeywords=knownLimitation,purejava" + }; + static { + Properties optionAliases = Harness.getOptionAliases(); + if (null != optionAliases) { + for (int i = 1; i < ALIASES.length; i += 2) { + optionAliases.put(ALIASES[i-1], ALIASES[i]); } - } - } - - /** controller for suppressing and sniffing error and output streams. */ - StreamsHandler streamsHandler; - - /** facility of hiding-streams may be applied in many features */ - IRunListener streamHider; - - /** facility of capture/log may be applied in many features */ - IRunListener captureLogger; - - /** when making tests, do not run them */ - TestMaker testMaker; - - public FeatureHarness() { - super(); - streamsHandler = new StreamsHandler(false, true); - } - /** override to make tests or run as usual */ - protected RunResult run(AjcTest.Suite.Spec spec) { - if (null != testMaker) { - System.out.println("generating rather than running tests..."); - return testMaker.run(spec); - } else { - return super.run(spec); - } - } - - /** - * Log via StreamsHandler-designated log stream. - * @see org.aspectj.testing.drivers.Harness#log(String) + } + } + + /** controller for suppressing and sniffing error and output streams. */ + StreamsHandler streamsHandler; + + /** facility of hiding-streams may be applied in many features */ + IRunListener streamHider; + + /** facility of capture/log may be applied in many features */ + IRunListener captureLogger; + + /** when making tests, do not run them */ + TestMaker testMaker; + + public FeatureHarness() { + super(); + streamsHandler = new StreamsHandler(false, true); + } + /** override to make tests or run as usual */ + @Override + protected RunResult run(AjcTest.Suite.Spec spec) { + if (null != testMaker) { + System.out.println("generating rather than running tests..."); + return testMaker.run(spec); + } else { + return super.run(spec); + } + } + + /** + * Log via StreamsHandler-designated log stream. + * @see org.aspectj.testing.drivers.Harness#log(String) */ + @Override protected void logln(String s) { if (!silentHarness) - streamsHandler.lnlog(s); + streamsHandler.lnlog(s); } - /** + /** * @see org.aspectj.testing.drivers.Harness#getLogStream() - * @return StreamsHandler-designated log stream. + * @return StreamsHandler-designated log stream. */ + @Override protected PrintStream getLogStream() { return streamsHandler.out; } - /** print detail message for syntax of main(String[]) command-line */ - protected void printSyntax(PrintStream out) { - super.printSyntax(out); - out.println(" -progressDots log . or ! for each AjcTest pass or fail"); - out.println(" -logFail log each failed AjcTest"); - out.println(" -logPass log each passed AjcTest"); - out.println(" -logAll log each AjcTest"); - out.println(" -logMinFail log each AjcTest failure with minimal excess data"); - out.println(" -logMinPass log each AjcTest success with minimal excess data"); - out.println(" -logMinAll log all AjcTest with minimal excess data"); - out.println(" -logXMLFail log XML definition for each failed AjcTest"); - out.println(" -logXMLPass log XML definition for each passed AjcTest"); - out.println(" -logXMLAll log XML definition for each AjcTest"); - out.println(" -logJUnit log all tests in JUnit XML report style"); - out.println(" -hideRunStreams hide err/out streams during java runs"); - out.println(" -hideCompilerStreams hide err/out streams during compiler runs"); - out.println(" -traceTests log pass|fail, /time/memory taken after each test"); - out.println(" -traceTestsMin log pass|fail after each test"); - out.println(" -XmakeTests create source files/dirs for initial compile run of each test"); - out.println(" -XlogPublicType log test XML if \"public type\" in an error message"); - out.println(" -XlogSourceIn=Y,Z log test XML if Y or Z is in path of any sources"); - super.printAliases(out); - } - - /** Accept a number of logging and output options */ + /** print detail message for syntax of main(String[]) command-line */ + @Override + protected void printSyntax(PrintStream out) { + super.printSyntax(out); + out.println(" -progressDots log . or ! for each AjcTest pass or fail"); + out.println(" -logFail log each failed AjcTest"); + out.println(" -logPass log each passed AjcTest"); + out.println(" -logAll log each AjcTest"); + out.println(" -logMinFail log each AjcTest failure with minimal excess data"); + out.println(" -logMinPass log each AjcTest success with minimal excess data"); + out.println(" -logMinAll log all AjcTest with minimal excess data"); + out.println(" -logXMLFail log XML definition for each failed AjcTest"); + out.println(" -logXMLPass log XML definition for each passed AjcTest"); + out.println(" -logXMLAll log XML definition for each AjcTest"); + out.println(" -logJUnit log all tests in JUnit XML report style"); + out.println(" -hideRunStreams hide err/out streams during java runs"); + out.println(" -hideCompilerStreams hide err/out streams during compiler runs"); + out.println(" -traceTests log pass|fail, /time/memory taken after each test"); + out.println(" -traceTestsMin log pass|fail after each test"); + out.println(" -XmakeTests create source files/dirs for initial compile run of each test"); + out.println(" -XlogPublicType log test XML if \"public type\" in an error message"); + out.println(" -XlogSourceIn=Y,Z log test XML if Y or Z is in path of any sources"); + super.printAliases(out); + } + + /** Accept a number of logging and output options */ + @Override protected boolean acceptOption(String option) { - if (null == option) { - return false; - } - - final StreamsHandler streams = streamsHandler; - final IRunValidator validator = RunValidator.NORMAL; - final RunUtils.IRunStatusPrinter verbose - = RunUtils.VERBOSE_PRINTER; - final RunUtils.IRunStatusPrinter terse - = RunUtils.TERSE_PRINTER; -// final boolean LOGPASS = true; -// final boolean LOGFAIL = true; -// final boolean SKIPPASS = false; -// final boolean SKIPFAIL = false; -// final boolean LOGSTREAMS = true; - final boolean SKIPSTREAMS = false; + if (null == option) { + return false; + } + + final StreamsHandler streams = streamsHandler; + final IRunValidator validator = RunValidator.NORMAL; + final RunUtils.IRunStatusPrinter verbose + = RunUtils.VERBOSE_PRINTER; + final RunUtils.IRunStatusPrinter terse + = RunUtils.TERSE_PRINTER; + // final boolean LOGPASS = true; + // final boolean LOGFAIL = true; + // final boolean SKIPPASS = false; + // final boolean SKIPFAIL = false; + // final boolean LOGSTREAMS = true; + final boolean SKIPSTREAMS = false; Feature feature = null; - if (super.acceptOption(option)) { - // ok, result returned below - - } else if ("-XmakeTests".equals(option)) { - testMaker = TestMaker.ME; - } else if (option.startsWith("-traceTestsMin")) { - feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, false)); - } else if (option.startsWith("-traceTests")) { - feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, true)); - } else if (option.startsWith("-logMin")) { - feature = new Feature(option, AjcTest.class, - new RunLogger(option, SKIPSTREAMS, streams, validator, terse)); - } else if (option.startsWith("-logXML")) { - feature = new Feature(option, AjcTest.class, - new XmlLogger(option, streams, validator)); - } else if (option.startsWith("-logJUnit")) { - feature = new Feature(option, AjcTest.class, - new JUnitXMLLogger(option,streams,validator)); - } else if (option.startsWith("-log")) { - feature = new Feature(option, AjcTest.class, - new RunLogger(option, SKIPSTREAMS, streams, validator, verbose)); - } else if ("-hideRunStreams".equals(option)) { - feature = new Feature(option, JavaRun.class, getStreamHider()); - } else if ("-hideCompilerStreams".equals(option)) { - addFeature(new Feature(option, IncCompilerRun.class, getStreamHider())); // hmmm - feature = new Feature(option, CompilerRun.class, getStreamHider()); - } else if ("-progressDots".equals(option)) { - IRunListener listener = new RunListener() { + if (super.acceptOption(option)) { + // ok, result returned below + + } else if ("-XmakeTests".equals(option)) { + testMaker = TestMaker.ME; + } else if (option.startsWith("-traceTestsMin")) { + feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, false)); + } else if (option.startsWith("-traceTests")) { + feature = new Feature(option, AjcTest.class,new TestTraceLogger(streams, true)); + } else if (option.startsWith("-logMin")) { + feature = new Feature(option, AjcTest.class, + new RunLogger(option, SKIPSTREAMS, streams, validator, terse)); + } else if (option.startsWith("-logXML")) { + feature = new Feature(option, AjcTest.class, + new XmlLogger(option, streams, validator)); + } else if (option.startsWith("-logJUnit")) { + feature = new Feature(option, AjcTest.class, + new JUnitXMLLogger(option,streams,validator)); + } else if (option.startsWith("-log")) { + feature = new Feature(option, AjcTest.class, + new RunLogger(option, SKIPSTREAMS, streams, validator, verbose)); + } else if ("-hideRunStreams".equals(option)) { + feature = new Feature(option, JavaRun.class, getStreamHider()); + } else if ("-hideCompilerStreams".equals(option)) { + addFeature(new Feature(option, IncCompilerRun.class, getStreamHider())); // hmmm + feature = new Feature(option, CompilerRun.class, getStreamHider()); + } else if ("-progressDots".equals(option)) { + IRunListener listener = new RunListener() { + @Override public void runCompleted(IRunStatus run) { - streamsHandler.log((validator.runPassed(run) ? "." : "!")); + streamsHandler.log((validator.runPassed(run) ? "." : "!")); } - }; - feature = new Feature(option, AjcTest.class, listener); - } else if (option.startsWith("-XlogPublicType")) { - String label = option + TestCompleteListener.PASS; // print when validator true - feature = new Feature(option, AjcTest.class, - new XmlLogger(label, streams, MessageRunValidator.PUBLIC_TYPE_ERROR)); - } else if (option.startsWith("-XlogSourceIn")) { - String input = option.substring("-XlogSourceIn=".length()); - LangUtil.throwIaxIfFalse(0 < input.length(), option); - String label = "-XlogSourceIn=" + TestCompleteListener.PASS; // print when validator true - StringRunner sr = new SubstringRunner(input, false); - feature = new Feature(option, AjcTest.class, - new XmlLogger(label, streams, new SourcePathValidator(sr))); - } else { - return false; - } - addFeature(feature); - return true; - } - - /** lazy construction for shared hider */ - protected IRunListener getStreamHider() { - if (null == streamHider) { - streamHider = new RunListener() { - public void runStarting(IRunStatus run) { - streamsHandler.hide(); - } - public void runCompleted(IRunStatus run) { - streamsHandler.show(); - } - public String toString() { return "Harness StreamHider"; } - }; - } - return streamHider; - } + }; + feature = new Feature(option, AjcTest.class, listener); + } else if (option.startsWith("-XlogPublicType")) { + String label = option + TestCompleteListener.PASS; // print when validator true + feature = new Feature(option, AjcTest.class, + new XmlLogger(label, streams, MessageRunValidator.PUBLIC_TYPE_ERROR)); + } else if (option.startsWith("-XlogSourceIn")) { + String input = option.substring("-XlogSourceIn=".length()); + LangUtil.throwIaxIfFalse(0 < input.length(), option); + String label = "-XlogSourceIn=" + TestCompleteListener.PASS; // print when validator true + StringRunner sr = new SubstringRunner(input, false); + feature = new Feature(option, AjcTest.class, + new XmlLogger(label, streams, new SourcePathValidator(sr))); + } else { + return false; + } + addFeature(feature); + return true; + } + + /** lazy construction for shared hider */ + protected IRunListener getStreamHider() { + if (null == streamHider) { + streamHider = new RunListener() { + @Override + public void runStarting(IRunStatus run) { + streamsHandler.hide(); + } + @Override + public void runCompleted(IRunStatus run) { + streamsHandler.show(); + } + @Override + public String toString() { return "Harness StreamHider"; } + }; + } + return streamHider; + } } /** Generate any needed test case files for any test. */ class TestMaker { - static TestMaker ME = new TestMaker(); - - /** @throws Error if unable to make dir */ - static void mkdirs(File dir) { - if (null != dir && !dir.exists()) { - if (!dir.mkdirs()) { - throw new Error("unable to make dir: " + dir); - } - } - } - static String getFileContents(File baseDir, File file, String label) { - String fileName = file.getName(); - if (fileName.endsWith(".java")) { - fileName = fileName.substring(0, fileName.length() - 5); - } - StringBuffer sb = new StringBuffer(); - String filePath = file.getParentFile().getAbsolutePath(); - String dirPath = baseDir.getAbsolutePath(); - String pack = null; - if (filePath.startsWith(dirPath)) { - pack = filePath.substring(dirPath.length()).replace('/', '.'); - } - if (!LangUtil.isEmpty(pack)) { - sb.append("package " + pack + ";"); - } - final String EOL = "\n"; // XXX find discovered EOL - sb.append( EOL - + EOL + "import org.aspectj.testing.Tester;" - + EOL + "" - + EOL + "/** @testcase " + label + " */" - + EOL + "public class " + fileName + " {" - + EOL + "\tpublic static void main(String[] args) { " - + EOL + "\t\tTester.check(null != args, \"null args\"); " - + EOL + "\t}" - + EOL + "}" - + EOL - ); - - return sb.toString(); - } - - /** create a minimal source file for a test */ - static void createSrcFile(File baseDir, File file, String testName) { - if (file.exists()) { - return; - } - String contents = getFileContents(baseDir, file, testName); - String error = FileUtil.writeAsString(file, contents); - if (null != error) { - throw new Error(error); - } - } - - /** create an empty arg file for a test */ - static void createArgFile(File baseDir, File file, String testName) { - if (file.exists()) { - return; - } - String contents = "// argfile " + file; - String error = FileUtil.writeAsString(file, contents); - if (null != error) { - throw new Error(error); - } - } - - public Harness.RunResult run(AjcTest.Suite.Spec spec) { - ArrayList kids = spec.getChildren(); - for (Iterator iter = kids.iterator(); iter.hasNext();) { - makeTest( (AjcTest.Spec) iter.next()); - } - IRunStatus status = new RunStatus(new MessageHandler(), new Runner()); - status.start(); - status.finish(IRunStatus.PASS); - return new Harness.RunResult(status, 0); - } - - private void makeTest(AjcTest.Spec spec) { - CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(spec); - if (null == spec) { - throw new Error("null spec"); - } - System.out.println(" generating test files for test: " + spec.getDescription()); - File dir = spec.getSuiteDir(); - if (null != dir) { - TestMaker.mkdirs(dir); - } - String offset = spec.getTestDirOffset(); - if (!LangUtil.isEmpty(offset)) { - if (null == dir) { - dir = new File(offset); - } else { - dir = new File(dir.getAbsolutePath() + "/" + offset); - } - } else if (null == dir) { - dir = new File("."); - } - StringBuffer testName = new StringBuffer(); - int pr = spec.getBugId(); - if (0 < pr) { - testName.append("PR#" + pr + " "); - } - - testName.append(spec.getDescription()); - final String label = testName.toString(); - final File[] srcFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getPathsArray()); - if (!LangUtil.isEmpty(srcFiles)) { - for (int i = 0; i < srcFiles.length; i++) { - TestMaker.createSrcFile(dir, srcFiles[i], label); - } - } - final File[] argFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getArgfilesArray()); - if (!LangUtil.isEmpty(argFiles)) { - for (int i = 0; i < argFiles.length; i++) { - TestMaker.createArgFile(dir, argFiles[i], label); - } - } - - } - - /** @return "Testmaker()" */ - public String toString() { - return "TestMaker()"; - } + static TestMaker ME = new TestMaker(); + + /** @throws Error if unable to make dir */ + static void mkdirs(File dir) { + if (null != dir && !dir.exists()) { + if (!dir.mkdirs()) { + throw new Error("unable to make dir: " + dir); + } + } + } + static String getFileContents(File baseDir, File file, String label) { + String fileName = file.getName(); + if (fileName.endsWith(".java")) { + fileName = fileName.substring(0, fileName.length() - 5); + } + StringBuffer sb = new StringBuffer(); + String filePath = file.getParentFile().getAbsolutePath(); + String dirPath = baseDir.getAbsolutePath(); + String pack = null; + if (filePath.startsWith(dirPath)) { + pack = filePath.substring(dirPath.length()).replace('/', '.'); + } + if (!LangUtil.isEmpty(pack)) { + sb.append("package " + pack + ";"); + } + final String EOL = "\n"; // XXX find discovered EOL + sb.append( EOL + + EOL + "import org.aspectj.testing.Tester;" + + EOL + "" + + EOL + "/** @testcase " + label + " */" + + EOL + "public class " + fileName + " {" + + EOL + "\tpublic static void main(String[] args) { " + + EOL + "\t\tTester.check(null != args, \"null args\"); " + + EOL + "\t}" + + EOL + "}" + + EOL + ); + + return sb.toString(); + } + + /** create a minimal source file for a test */ + static void createSrcFile(File baseDir, File file, String testName) { + if (file.exists()) { + return; + } + String contents = getFileContents(baseDir, file, testName); + String error = FileUtil.writeAsString(file, contents); + if (null != error) { + throw new Error(error); + } + } + + /** create an empty arg file for a test */ + static void createArgFile(File baseDir, File file, String testName) { + if (file.exists()) { + return; + } + String contents = "// argfile " + file; + String error = FileUtil.writeAsString(file, contents); + if (null != error) { + throw new Error(error); + } + } + + public Harness.RunResult run(AjcTest.Suite.Spec spec) { + ArrayList<IRunSpec> kids = spec.getChildren(); + for (IRunSpec iRunSpec : kids) { + makeTest( (AjcTest.Spec) iRunSpec); + } + IRunStatus status = new RunStatus(new MessageHandler(), new Runner()); + status.start(); + status.finish(IRunStatus.PASS); + return new Harness.RunResult(status, 0); + } + + private void makeTest(AjcTest.Spec spec) { + CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(spec); + if (null == spec) { + throw new Error("null spec"); + } + System.out.println(" generating test files for test: " + spec.getDescription()); + File dir = spec.getSuiteDir(); + if (null != dir) { + TestMaker.mkdirs(dir); + } + String offset = spec.getTestDirOffset(); + if (!LangUtil.isEmpty(offset)) { + if (null == dir) { + dir = new File(offset); + } else { + dir = new File(dir.getAbsolutePath() + "/" + offset); + } + } else if (null == dir) { + dir = new File("."); + } + StringBuffer testName = new StringBuffer(); + int pr = spec.getBugId(); + if (0 < pr) { + testName.append("PR#" + pr + " "); + } + + testName.append(spec.getDescription()); + final String label = testName.toString(); + final File[] srcFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getPathsArray()); + if (!LangUtil.isEmpty(srcFiles)) { + for (File srcFile : srcFiles) { + TestMaker.createSrcFile(dir, srcFile, label); + } + } + final File[] argFiles = FileUtil.getBaseDirFiles(dir, compileSpec.getArgfilesArray()); + if (!LangUtil.isEmpty(argFiles)) { + for (File argFile : argFiles) { + TestMaker.createArgFile(dir, argFile, label); + } + } + + } + + /** @return "Testmaker()" */ + @Override + public String toString() { + return "TestMaker()"; + } } interface StringRunner { - boolean accept(String s); + boolean accept(String s); } /** @@ -1000,56 +1011,57 @@ interface StringRunner { * optionally case-insensitive. */ class SubstringRunner implements StringRunner { - private static String[] extractSubstrings( - String substrings, - boolean caseSensitive) { - if (null == substrings) { - return null; - } - StringTokenizer st = new StringTokenizer(substrings, ","); - String[] result = new String[st.countTokens()]; - for (int i = 0; i < result.length; i++) { + private static String[] extractSubstrings( + String substrings, + boolean caseSensitive) { + if (null == substrings) { + return null; + } + StringTokenizer st = new StringTokenizer(substrings, ","); + String[] result = new String[st.countTokens()]; + for (int i = 0; i < result.length; i++) { result[i] = st.nextToken().trim(); - LangUtil.throwIaxIfFalse(0 < result[i].length(), "empty entry"); - if (!caseSensitive) { - result[i] = result[i].toLowerCase(); - } - } - return result; - } - - private final String[] substrings; - private final boolean caseSensitive; - - /** - * @param substrings the String containing comma-separated substrings - * to find in input - if null, any input accepted - * @param caseSensitive if true, do case-sensitive comparison - * @throws IllegalArgumentException if any substrings contains empty entry ", ," - */ - SubstringRunner(String substrings, boolean caseSensitive) { - this.caseSensitive = caseSensitive; - this.substrings = extractSubstrings(substrings, caseSensitive); - } - - public boolean accept(String input) { - if (null == substrings) { - return true; - } - if (null == input) { - return false; - } - - if (!caseSensitive) { - input = input.toLowerCase(); - } - for (int i = 0; i < substrings.length; i++) { - if (-1 != input.indexOf(substrings[i])) { - return true; - } - } - return false; - } + LangUtil.throwIaxIfFalse(0 < result[i].length(), "empty entry"); + if (!caseSensitive) { + result[i] = result[i].toLowerCase(); + } + } + return result; + } + + private final String[] substrings; + private final boolean caseSensitive; + + /** + * @param substrings the String containing comma-separated substrings + * to find in input - if null, any input accepted + * @param caseSensitive if true, do case-sensitive comparison + * @throws IllegalArgumentException if any substrings contains empty entry ", ," + */ + SubstringRunner(String substrings, boolean caseSensitive) { + this.caseSensitive = caseSensitive; + this.substrings = extractSubstrings(substrings, caseSensitive); + } + + @Override + public boolean accept(String input) { + if (null == substrings) { + return true; + } + if (null == input) { + return false; + } + + if (!caseSensitive) { + input = input.toLowerCase(); + } + for (String substring : substrings) { + if (-1 != input.indexOf(substring)) { + return true; + } + } + return false; + } } /** @@ -1057,30 +1069,31 @@ class SubstringRunner implements StringRunner { * (Static evaluation - no run necessary) */ class SourcePathValidator implements IRunValidator { // static - no run needed - private final StringRunner validator; - // XXX hoist common - SourcePathValidator(StringRunner validator) { - LangUtil.throwIaxIfNull(validator, "validator"); - this.validator = validator; - } - /** - * @return true if any source files in compile spec are - * accepted by the validator. + private final StringRunner validator; + // XXX hoist common + SourcePathValidator(StringRunner validator) { + LangUtil.throwIaxIfNull(validator, "validator"); + this.validator = validator; + } + /** + * @return true if any source files in compile spec are + * accepted by the validator. * @see org.aspectj.testing.run.IRunValidator#runPassed(IRunStatus) */ + @Override public boolean runPassed(IRunStatus run) { - AjcTest.Spec testSpec = AjcTest.unwrapSpec(run); - if (null != testSpec) { - CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(testSpec); - File basedir = new File(testSpec.getSuiteDir(), testSpec.getTestDirOffset()); - String[] paths = compileSpec.getPathsArray(); - File[] files = FileUtil.getBaseDirFiles(basedir, paths); - for (int i = 0; i < files.length; i++) { - if (validator.accept(files[i].getAbsolutePath())) { - return true; - } + AjcTest.Spec testSpec = AjcTest.unwrapSpec(run); + if (null != testSpec) { + CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(testSpec); + File basedir = new File(testSpec.getSuiteDir(), testSpec.getTestDirOffset()); + String[] paths = compileSpec.getPathsArray(); + File[] files = FileUtil.getBaseDirFiles(basedir, paths); + for (File file : files) { + if (validator.accept(file.getAbsolutePath())) { + return true; + } } - } + } return false; } @@ -1089,65 +1102,65 @@ class SourcePathValidator implements IRunValidator { // static - no run needed /** Signal whether run "passed" based on message kind and content */ class MessageRunValidator implements IRunValidator { - /** signals "passed" if any error contains "public type" */ - static final IRunValidator PUBLIC_TYPE_ERROR - = new MessageRunValidator("public type", IMessage.ERROR, false); - - private final IMessage.Kind kind; - private final String sought; - private final boolean orGreater; - - /** - * @param sought the String to seek anywhere in any message of the right kind - * if null, accept any message of the right kind. - * @param kind the IMessage.Kind of messages to search - all if null - */ - MessageRunValidator(String sought, IMessage.Kind kind, boolean orGreater) { - this.sought = sought; - this.kind = kind; - this.orGreater = orGreater; - } - - /** @return true if this run has messages of the right kind and text */ + /** signals "passed" if any error contains "public type" */ + static final IRunValidator PUBLIC_TYPE_ERROR + = new MessageRunValidator("public type", IMessage.ERROR, false); + + private final IMessage.Kind kind; + private final String sought; + private final boolean orGreater; + + /** + * @param sought the String to seek anywhere in any message of the right kind + * if null, accept any message of the right kind. + * @param kind the IMessage.Kind of messages to search - all if null + */ + MessageRunValidator(String sought, IMessage.Kind kind, boolean orGreater) { + this.sought = sought; + this.kind = kind; + this.orGreater = orGreater; + } + + /** @return true if this run has messages of the right kind and text */ + @Override public boolean runPassed(IRunStatus run) { - return gotMessage(new IRunStatus[] {run}); - } - - /** - * Search these children and their children recursively - * for messages of the right kind and content. - * @return true at first match of message of the right kind and content - */ - private boolean gotMessage(IRunStatus[] children) { - if (LangUtil.isEmpty(children)) { - return false; - } - for (int i = 0; i < children.length; i++) { - IRunStatus run = children[i]; - if (null == run) { - continue; // hmm - } - IMessage[] messages = run.getMessages(kind, orGreater); - if (!LangUtil.isEmpty(messages)) { - if (LangUtil.isEmpty(sought)) { - return true; - } else { - for (int j = 0; j < messages.length; j++) { - if (null == messages[j]) { - continue; // hmm - } - String text = messages[j].getMessage(); - if ((null != text) && (-1 != text.indexOf(sought))) { - return true; - } - } - } - } - if (gotMessage(run.getChildren())) { - return true; - } - } - return false; + return gotMessage(new IRunStatus[] {run}); + } + + /** + * Search these children and their children recursively + * for messages of the right kind and content. + * @return true at first match of message of the right kind and content + */ + private boolean gotMessage(IRunStatus[] children) { + if (LangUtil.isEmpty(children)) { + return false; + } + for (IRunStatus run : children) { + if (null == run) { + continue; // hmm + } + IMessage[] messages = run.getMessages(kind, orGreater); + if (!LangUtil.isEmpty(messages)) { + if (LangUtil.isEmpty(sought)) { + return true; + } else { + for (IMessage message : messages) { + if (null == message) { + continue; // hmm + } + String text = message.getMessage(); + if ((null != text) && (-1 != text.indexOf(sought))) { + return true; + } + } + } + } + if (gotMessage(run.getChildren())) { + return true; + } + } + return false; } } @@ -1157,105 +1170,107 @@ class MessageRunValidator implements IRunValidator { * Subclasses implement doRunCompleted(..). */ abstract class TestCompleteListener extends RunListener { - /** label suffix indicating both pass and fail */ - public static final String ALL = "All"; - - /** label suffix indicating fail */ - public static final String FAIL = "Fail"; - - /** label suffix indicating pass */ - public static final String PASS = "Pass"; - - - /** runValidator determines if a given run passed */ - protected final IRunValidator runValidator; - - /** label for this listener */ - final String label; - - /** if trun and run passed, then run doRunCompleted(..) */ - final boolean logOnPass; - - /** if true and run did not pass, then run doRunCompleted(..) */ - final boolean logOnNotPass; - - /** may be null */ - protected final StreamsHandler streamsHandler; - - /** true if the last run evaluation was ok */ - boolean lastRunOk; - - /** last run evaluated */ - IRunStatus lastRun; // XXX small memory leak - cache hashcode instead? - - /** @param label endsWith PASS || FAIL || ALL */ - protected TestCompleteListener( - String label, - IRunValidator runValidator, - StreamsHandler streamsHandler) { - if (null == runValidator) { - runValidator = RunValidator.NORMAL; - } - this.label = (null == label? "" : label); - this.logOnPass = label.endsWith(PASS) || label.endsWith(ALL); - this.logOnNotPass = label.endsWith(FAIL) || label.endsWith(ALL); - this.runValidator = runValidator; - this.streamsHandler = streamsHandler; - } - - public void runStarted(IRunStatus run) { - if (null != streamsHandler) { - streamsHandler.startListening(); - } - } - - /** subclasses implement this to do some per-test initialization */ - protected void doRunStarted(IRunStatus run) { - } - - - /** subclasses implement this to do some per-suite initialization */ - protected void doStartSuite(File suite) { - } - - /** subclasses implement this to do end-of-suite processing */ - protected void doEndSuite(File suite, long duration) { - } - - public final void runCompleted(IRunStatus run) { - boolean doit = lastRunOk(run); - StreamsHandler.Result result = null; - if (null != streamsHandler) { - streamsHandler.endListening(doit); - } - if (doit) { - doRunCompleted(run, result); - } - } - - /** - * @return true if run is ok per constructor specifications - */ - protected boolean lastRunOk(IRunStatus run) { - if (lastRun != run) { - boolean passed = runValidator.runPassed(run); - lastRunOk = (passed ? logOnPass : logOnNotPass); - } - return lastRunOk; - } - - /** @return "{classname}({pass}{,fail})" indicating when this runs */ - public String toString() { // XXX add label? - return LangUtil.unqualifiedClassName(this) - + "(" + (logOnPass ? (logOnNotPass ? "pass, fail)" : "pass)") - : (logOnNotPass ? "fail)" : ")")); - } - /** - * Subclasses implement this to do some completion action - * @param run the IRunStatus for this completed run - * @param result the StreamsHandler.Result (if any - may be null) - */ - public abstract void doRunCompleted(IRunStatus run, StreamsHandler.Result result); + /** label suffix indicating both pass and fail */ + public static final String ALL = "All"; + + /** label suffix indicating fail */ + public static final String FAIL = "Fail"; + + /** label suffix indicating pass */ + public static final String PASS = "Pass"; + + + /** runValidator determines if a given run passed */ + protected final IRunValidator runValidator; + + /** label for this listener */ + final String label; + + /** if trun and run passed, then run doRunCompleted(..) */ + final boolean logOnPass; + + /** if true and run did not pass, then run doRunCompleted(..) */ + final boolean logOnNotPass; + + /** may be null */ + protected final StreamsHandler streamsHandler; + + /** true if the last run evaluation was ok */ + boolean lastRunOk; + + /** last run evaluated */ + IRunStatus lastRun; // XXX small memory leak - cache hashcode instead? + + /** @param label endsWith PASS || FAIL || ALL */ + protected TestCompleteListener( + String label, + IRunValidator runValidator, + StreamsHandler streamsHandler) { + if (null == runValidator) { + runValidator = RunValidator.NORMAL; + } + this.label = (null == label? "" : label); + this.logOnPass = label.endsWith(PASS) || label.endsWith(ALL); + this.logOnNotPass = label.endsWith(FAIL) || label.endsWith(ALL); + this.runValidator = runValidator; + this.streamsHandler = streamsHandler; + } + + public void runStarted(IRunStatus run) { + if (null != streamsHandler) { + streamsHandler.startListening(); + } + } + + /** subclasses implement this to do some per-test initialization */ + protected void doRunStarted(IRunStatus run) { + } + + + /** subclasses implement this to do some per-suite initialization */ + protected void doStartSuite(File suite) { + } + + /** subclasses implement this to do end-of-suite processing */ + protected void doEndSuite(File suite, long duration) { + } + + @Override + public final void runCompleted(IRunStatus run) { + boolean doit = lastRunOk(run); + StreamsHandler.Result result = null; + if (null != streamsHandler) { + streamsHandler.endListening(doit); + } + if (doit) { + doRunCompleted(run, result); + } + } + + /** + * @return true if run is ok per constructor specifications + */ + protected boolean lastRunOk(IRunStatus run) { + if (lastRun != run) { + boolean passed = runValidator.runPassed(run); + lastRunOk = (passed ? logOnPass : logOnNotPass); + } + return lastRunOk; + } + + /** @return "{classname}({pass}{,fail})" indicating when this runs */ + @Override + public String toString() { // XXX add label? + return LangUtil.unqualifiedClassName(this) + + "(" + (logOnPass ? (logOnNotPass ? "pass, fail)" : "pass)") + : (logOnNotPass ? "fail)" : ")")); + } + /** + * Subclasses implement this to do some completion action + * @param run the IRunStatus for this completed run + * @param result the StreamsHandler.Result (if any - may be null) + */ + public abstract void doRunCompleted(IRunStatus run, StreamsHandler.Result result); } /** @@ -1264,36 +1279,37 @@ abstract class TestCompleteListener extends RunListener { * most sensibly AjcTest.class. */ class XmlLogger extends TestCompleteListener { - /** - * @param printer the component that prints any status - not null - * @param runValidator if null, use RunValidator.NORMAL - */ - public XmlLogger( - String label, - StreamsHandler streamsHandler, - IRunValidator runValidator) { - super(label, runValidator, streamsHandler); - } - - public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { - PrintStream out = streamsHandler.getLogStream(); - out.println(""); - XMLWriter writer = new XMLWriter(new PrintWriter(out, true)); - Object id = run.getIdentifier(); - if (!(id instanceof Runner.IteratorWrapper)) { - out.println(this + " not IteratorWrapper: " - + id.getClass().getName() + ": " + id); - return; - } - IRunIterator iter = ((Runner.IteratorWrapper) id).iterator; - if (!(iter instanceof RunSpecIterator)) { - out.println(this + " not RunSpecIterator: " + iter.getClass().getName() - + ": " + iter); - return; - } - ((RunSpecIterator) iter).spec.writeXml(writer); - out.flush(); - } + /** + * @param printer the component that prints any status - not null + * @param runValidator if null, use RunValidator.NORMAL + */ + public XmlLogger( + String label, + StreamsHandler streamsHandler, + IRunValidator runValidator) { + super(label, runValidator, streamsHandler); + } + + @Override + public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { + PrintStream out = streamsHandler.getLogStream(); + out.println(""); + XMLWriter writer = new XMLWriter(new PrintWriter(out, true)); + Object id = run.getIdentifier(); + if (!(id instanceof Runner.IteratorWrapper)) { + out.println(this + " not IteratorWrapper: " + + id.getClass().getName() + ": " + id); + return; + } + IRunIterator iter = ((Runner.IteratorWrapper) id).iterator; + if (!(iter instanceof RunSpecIterator)) { + out.println(this + " not RunSpecIterator: " + iter.getClass().getName() + + ": " + iter); + return; + } + ((RunSpecIterator) iter).spec.writeXml(writer); + out.flush(); + } } @@ -1312,24 +1328,25 @@ class XmlLogger extends TestCompleteListener { */ class JUnitXMLLogger extends TestCompleteListener { -// private File suite; - private StringBuffer junitOutput; - private long startTimeMillis; - private int numTests = 0; - private int numFails = 0; - private DecimalFormat timeFormatter = new DecimalFormat("#.##"); - - public JUnitXMLLogger( - String label, - StreamsHandler streamsHandler, - IRunValidator runValidator) { - super(label + ALL, runValidator, streamsHandler); - junitOutput = new StringBuffer(); - } + // private File suite; + private StringBuffer junitOutput; + private long startTimeMillis; + private int numTests = 0; + private int numFails = 0; + private DecimalFormat timeFormatter = new DecimalFormat("#.##"); + + public JUnitXMLLogger( + String label, + StreamsHandler streamsHandler, + IRunValidator runValidator) { + super(label + ALL, runValidator, streamsHandler); + junitOutput = new StringBuffer(); + } /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#doRunCompleted(org.aspectj.testing.run.IRunStatus, org.aspectj.testing.util.StreamsHandler.Result) */ + @Override public void doRunCompleted(IRunStatus run, Result result) { long duration = System.currentTimeMillis() - startTimeMillis; numTests++; @@ -1340,8 +1357,8 @@ class JUnitXMLLogger extends TestCompleteListener { numFails++; junitOutput.append("\n"); junitOutput.append("<failure message=\"test failed\" type=\"unknown\">\n"); -// junitOutput.println(result.junitOutput); -// junitOutput.println(result.err); + // junitOutput.println(result.junitOutput); + // junitOutput.println(result.err); junitOutput.append("</failure>\n"); } junitOutput.append("</testcase>\n"); @@ -1350,14 +1367,16 @@ class JUnitXMLLogger extends TestCompleteListener { /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#runStarted(org.aspectj.testing.run.IRunStatus) */ + @Override public void runStarting(IRunStatus run) { - super.runStarting(run); - startTimeMillis = System.currentTimeMillis(); + super.runStarting(run); + startTimeMillis = System.currentTimeMillis(); } /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#doEndSuite(java.io.File, long) */ + @Override protected void doEndSuite(File suite, long duration) { super.doEndSuite(suite, duration); String suiteName = suite.getName(); @@ -1376,9 +1395,10 @@ class JUnitXMLLogger extends TestCompleteListener { /* (non-Javadoc) * @see org.aspectj.testing.drivers.TestCompleteListener#doStartSuite(java.io.File) */ + @Override protected void doStartSuite(File suite) { super.doStartSuite(suite); -// this.suite = suite; + // this.suite = suite; numTests = 0; numFails = 0; junitOutput = new StringBuffer(); @@ -1388,98 +1408,101 @@ class JUnitXMLLogger extends TestCompleteListener { /** log pass and/or failed runs */ class RunLogger extends TestCompleteListener { - final boolean logStreams; - final RunUtils.IRunStatusPrinter printer; - - /** - * @param printer the component that prints any status - not null - * @param runValidator if null, use RunValidator.NORMAL - */ - public RunLogger( - String label, - boolean logStreams, - StreamsHandler streamsHandler, - IRunValidator runValidator, - RunUtils.IRunStatusPrinter printer) { - super(label, runValidator, streamsHandler); - LangUtil.throwIaxIfNull(streamsHandler, "streamsHandler"); - LangUtil.throwIaxIfNull(printer, "printer"); - this.logStreams = logStreams; - this.printer = printer; - } - - public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { - PrintStream out = streamsHandler.getLogStream(); - printer.printRunStatus(out, run); - if (logStreams) { - if (!LangUtil.isEmpty(result.err)) { - out.println("--- error"); - out.println(result.err); - } - if (!LangUtil.isEmpty(result.out)) { - out.println("--- ouput"); - out.println(result.out); - } - } - out.println(""); - } + final boolean logStreams; + final RunUtils.IRunStatusPrinter printer; + + /** + * @param printer the component that prints any status - not null + * @param runValidator if null, use RunValidator.NORMAL + */ + public RunLogger( + String label, + boolean logStreams, + StreamsHandler streamsHandler, + IRunValidator runValidator, + RunUtils.IRunStatusPrinter printer) { + super(label, runValidator, streamsHandler); + LangUtil.throwIaxIfNull(streamsHandler, "streamsHandler"); + LangUtil.throwIaxIfNull(printer, "printer"); + this.logStreams = logStreams; + this.printer = printer; + } + + @Override + public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { + PrintStream out = streamsHandler.getLogStream(); + printer.printRunStatus(out, run); + if (logStreams) { + if (!LangUtil.isEmpty(result.err)) { + out.println("--- error"); + out.println(result.err); + } + if (!LangUtil.isEmpty(result.out)) { + out.println("--- ouput"); + out.println(result.out); + } + } + out.println(""); + } } /** trace time and memory between runStaring and runCompleted */ class TestTraceLogger extends TestCompleteListener { - private static final Runtime runtime = Runtime.getRuntime(); - private long startTime; - private long startMemoryFree; - private final boolean verbose; - - public TestTraceLogger(StreamsHandler handler) { - this(handler, true); - } - public TestTraceLogger(StreamsHandler handler, boolean verbose) { - super("-traceTestsAll", null, handler); - this.verbose = verbose; - } - public void runStarting(IRunStatus run) { - super.runStarting(run); - startTime = System.currentTimeMillis(); - startMemoryFree = runtime.freeMemory(); - } - - public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { - long elapsed = System.currentTimeMillis() - startTime; - long free = runtime.freeMemory(); - long used = startMemoryFree - free; - String label = run.runResult() ? "PASS " : "FAIL "; - PrintStream out = streamsHandler.getLogStream(); - if (verbose) { - label = label - + "elapsed: " + LangUtil.toSizedString(elapsed, 7) - + " free: " + LangUtil.toSizedString(free, 10) - + " used: " + LangUtil.toSizedString(used, 10) - + " id: "; - } - out.println(label + renderId(run)); - } - - /** @return true - always trace tests */ - protected boolean isFailLabel(String label) { - return true; - } - - /** @return true - always trace tests */ - protected boolean isPassLabel(String label) { - return true; - } - - /** - * This implementation returns run identifier toString(). - * Subclasses override this to render id as message suffix. - */ - protected String renderId(IRunStatus run) { - return "" + run.getIdentifier(); - } + private static final Runtime runtime = Runtime.getRuntime(); + private long startTime; + private long startMemoryFree; + private final boolean verbose; + + public TestTraceLogger(StreamsHandler handler) { + this(handler, true); + } + public TestTraceLogger(StreamsHandler handler, boolean verbose) { + super("-traceTestsAll", null, handler); + this.verbose = verbose; + } + @Override + public void runStarting(IRunStatus run) { + super.runStarting(run); + startTime = System.currentTimeMillis(); + startMemoryFree = runtime.freeMemory(); + } + + @Override + public void doRunCompleted(IRunStatus run, StreamsHandler.Result result) { + long elapsed = System.currentTimeMillis() - startTime; + long free = runtime.freeMemory(); + long used = startMemoryFree - free; + String label = run.runResult() ? "PASS " : "FAIL "; + PrintStream out = streamsHandler.getLogStream(); + if (verbose) { + label = label + + "elapsed: " + LangUtil.toSizedString(elapsed, 7) + + " free: " + LangUtil.toSizedString(free, 10) + + " used: " + LangUtil.toSizedString(used, 10) + + " id: "; + } + out.println(label + renderId(run)); + } + + /** @return true - always trace tests */ + protected boolean isFailLabel(String label) { + return true; + } + + /** @return true - always trace tests */ + protected boolean isPassLabel(String label) { + return true; + } + + /** + * This implementation returns run identifier toString(). + * Subclasses override this to render id as message suffix. + */ + protected String renderId(IRunStatus run) { + return "" + run.getIdentifier(); + } } - // printing files +// printing files // AjcTest.Spec testSpec = AjcTest.unwrapSpec(run); // if (null != testSpec) { // CompilerRun.Spec compileSpec = AjcTest.unwrapCompilerRunSpec(testSpec); |