junit test suite based on an ajcTests.xml format test specification.
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="testsrc"/>
- <classpathentry kind="var" path="JRE_LIB" sourcepath="JRE_SRC"/>
- <classpathentry kind="lib" path="/lib/ant/lib/ant.jar" sourcepath="/lib/ant/ant-src.zip"/>
- <classpathentry kind="lib" path="/lib/junit/junit.jar" sourcepath="/lib/junit/junit-src.jar"/>
- <classpathentry kind="lib" path="/lib/jdiff/jdiff.jar"/>
- <classpathentry kind="lib" path="/lib/regexp/jakarta-regexp-1.2.jar"/>
- <classpathentry kind="src" path="/bridge"/>
- <classpathentry kind="src" path="/util"/>
- <classpathentry kind="src" path="/testing-client"/>
- <classpathentry kind="lib" path="/lib/ant/lib/xercesImpl.jar"/>
- <classpathentry kind="lib" path="/lib/ant/lib/xml-apis.jar"/>
- <classpathentry kind="lib" path="/lib/commons/commons.jar" sourcepath="/lib/commons/commons-src.zip"/>
- <classpathentry kind="src" path="/testing-util"/>
- <classpathentry kind="src" path="/ajde"/>
- <classpathentry kind="src" path="/asm"/>
- <classpathentry kind="src" path="/taskdefs"/>
- <classpathentry kind="output" path="bin"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="testsrc"/>
+ <classpathentry sourcepath="JRE_SRC" kind="var" path="JRE_LIB"/>
+ <classpathentry sourcepath="/lib/ant/ant-src.zip" kind="lib" path="/lib/ant/lib/ant.jar"/>
+ <classpathentry sourcepath="/lib/junit/junit-src.jar" kind="lib" path="/lib/junit/junit.jar"/>
+ <classpathentry kind="lib" path="/lib/jdiff/jdiff.jar"/>
+ <classpathentry kind="lib" path="/lib/regexp/jakarta-regexp-1.2.jar"/>
+ <classpathentry kind="src" path="/bridge"/>
+ <classpathentry kind="src" path="/util"/>
+ <classpathentry kind="src" path="/testing-client"/>
+ <classpathentry kind="lib" path="/lib/ant/lib/xercesImpl.jar"/>
+ <classpathentry kind="lib" path="/lib/ant/lib/xml-apis.jar"/>
+ <classpathentry sourcepath="/lib/commons/commons-src.zip" kind="lib" path="/lib/commons/commons.jar"/>
+ <classpathentry kind="src" path="/testing-util"/>
+ <classpathentry kind="src" path="/ajde"/>
+ <classpathentry kind="src" path="/asm"/>
+ <classpathentry kind="src" path="/taskdefs"/>
+ <classpathentry kind="src" path="newsrc"/>
+ <classpathentry kind="src" path="/org.aspectj.ajdt.core"/>
+ <classpathentry kind="output" path="bin"/>
</classpath>
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer,
+ * ******************************************************************/
+package org.aspectj.testing;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.aspectj.tools.ajc.AjcTestCase;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class AjcTest {
+
+ private List testSteps = new ArrayList();
+
+ private String dir;
+ private String pr;
+ private String title;
+ private String keywords;
+ private String comment;
+
+ public AjcTest() {
+ }
+
+ public void addTestStep(ITestStep step) {
+ testSteps.add(step);
+ step.setTest(this);
+ }
+
+ public void runTest(AjcTestCase testCase) {
+ try {
+ System.out.print("TEST: " + getTitle() + "\t");
+ for (Iterator iter = testSteps.iterator(); iter.hasNext();) {
+ ITestStep step = (ITestStep) iter.next();
+ step.setBaseDir(getDir());
+ System.out.print(".");
+ step.execute(testCase);
+ }
+ } finally {
+ System.out.println("DONE");
+ }
+ }
+
+ /**
+ * @return Returns the comment.
+ */
+ public String getComment() {
+ return comment;
+ }
+ /**
+ * @param comment The comment to set.
+ */
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+ /**
+ * @return Returns the dir.
+ */
+ public String getDir() {
+ return dir;
+ }
+ /**
+ * @param dir The dir to set.
+ */
+ public void setDir(String dir) {
+ dir = "../tests/" + dir;
+ this.dir = dir;
+ }
+ /**
+ * @return Returns the keywords.
+ */
+ public String getKeywords() {
+ return keywords;
+ }
+ /**
+ * @param keywords The keywords to set.
+ */
+ public void setKeywords(String keywords) {
+ this.keywords = keywords;
+ }
+ /**
+ * @return Returns the pr.
+ */
+ public String getPr() {
+ return pr;
+ }
+ /**
+ * @param pr The pr to set.
+ */
+ public void setPr(String pr) {
+ this.pr = pr;
+ }
+ /**
+ * @return Returns the title.
+ */
+ public String getTitle() {
+ return title;
+ }
+ /**
+ * @param title The title to set.
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer,
+ * ******************************************************************/
+package org.aspectj.testing;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.aspectj.tools.ajc.AjcTestCase;
+import org.aspectj.tools.ajc.CompilationResult;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class CompileSpec implements ITestStep {
+
+ private List expected = new ArrayList();
+
+ private String files;
+ private boolean includeClassesDir;
+ private String aspectpath;
+ private String classpath;
+ private String inpath;
+ private String sourceroots;
+ private String outjar;
+ private String xlintfile;
+ private String options;
+ private String baseDir;
+ private String extdirs;
+ private AjcTest myTest;
+
+ public CompileSpec() {
+ }
+
+ public void execute(AjcTestCase inTestCase) {
+ File base = new File(baseDir);
+ String[] args = buildArgs();
+ CompilationResult result = inTestCase.ajc(base,args);
+ AjcTestCase.MessageSpec messageSpec = buildMessageSpec();
+ String failMessage = "test \"" + myTest.getTitle() + "\" failed";
+ inTestCase.assertMessages(result,failMessage,messageSpec);
+ inTestCase.setShouldEmptySandbox(false); // so subsequent steps in same test see my results
+ }
+
+ public void addExpectedMessage(ExpectedMessageSpec message) {
+ expected.add(message);
+ }
+
+ public void setBaseDir(String dir) {
+ this.baseDir = dir;
+ }
+
+ public void setTest(AjcTest t) {
+ this.myTest = t;
+ }
+
+ /**
+ * @return Returns the aspectpath.
+ */
+ public String getAspectpath() {
+ return aspectpath;
+ }
+ /**
+ * @param aspectpath The aspectpath to set.
+ */
+ public void setAspectpath(String aspectpath) {
+ this.aspectpath = aspectpath.replace(',',File.pathSeparatorChar);
+ }
+ /**
+ * @return Returns the classpath.
+ */
+ public String getClasspath() {
+ return classpath;
+ }
+ /**
+ * @param classpath The classpath to set.
+ */
+ public void setClasspath(String classpath) {
+ this.classpath = classpath.replace(',',File.pathSeparatorChar);
+ }
+ /**
+ * @return Returns the files.
+ */
+ public String getFiles() {
+ return files;
+ }
+ /**
+ * @param files The files to set.
+ */
+ public void setFiles(String files) {
+ this.files = files;
+ }
+ /**
+ * @return Returns the includeClassesDir.
+ */
+ public boolean isIncludeClassesDir() {
+ return includeClassesDir;
+ }
+ /**
+ * @param includeClassesDir The includeClassesDir to set.
+ */
+ public void setIncludeClassesDir(boolean includeClassesDir) {
+ this.includeClassesDir = includeClassesDir;
+ }
+ /**
+ * @return Returns the inpath.
+ */
+ public String getInpath() {
+ return inpath;
+ }
+ /**
+ * @param inpath The inpath to set.
+ */
+ public void setInpath(String inpath) {
+ this.inpath = inpath.replace(',',File.pathSeparatorChar);
+ }
+ /**
+ * @return Returns the options.
+ */
+ public String getOptions() {
+ return options;
+ }
+ /**
+ * @param options The options to set.
+ */
+ public void setOptions(String options) {
+ int i = options.indexOf("!eclipse");
+ if (i != -1) {
+ this.options = options.substring(0,i);
+ this.options += options.substring(i + "!eclipse".length());
+ } else {
+ this.options = options;
+ }
+ }
+ /**
+ * @return Returns the outjar.
+ */
+ public String getOutjar() {
+ return outjar;
+ }
+ /**
+ * @param outjar The outjar to set.
+ */
+ public void setOutjar(String outjar) {
+ this.outjar = outjar;
+ }
+ /**
+ * @return Returns the sourceroots.
+ */
+ public String getSourceroots() {
+ return sourceroots;
+ }
+ /**
+ * @param sourceroots The sourceroots to set.
+ */
+ public void setSourceroots(String sourceroots) {
+ this.sourceroots = sourceroots;
+ }
+ /**
+ * @return Returns the xlintfile.
+ */
+ public String getXlintfile() {
+ return xlintfile;
+ }
+ /**
+ * @param xlintfile The xlintfile to set.
+ */
+ public void setXlintfile(String xlintfile) {
+ this.xlintfile = xlintfile;
+ }
+
+ public String getExtdirs() { return extdirs;}
+ public void setExtdirs(String extdirs) { this.extdirs = extdirs; }
+
+ private String[] buildArgs() {
+ StringBuffer args = new StringBuffer();
+ // add any set options, and then files to compile at the end
+ if (getAspectpath() != null) {
+ args.append("-aspectpath ");
+ args.append(getAspectpath());
+ args.append(" ");
+ }
+ if (getSourceroots() != null) {
+ args.append("-sourceroots ");
+ args.append(getSourceroots());
+ args.append(" ");
+ }
+ if (getOutjar() != null) {
+ args.append("-outjar ");
+ args.append(getOutjar());
+ args.append(" ");
+ }
+ if (getOptions() != null) {
+ StringTokenizer strTok = new StringTokenizer(getOptions(),",");
+ while (strTok.hasMoreTokens()) {
+ args.append(strTok.nextToken());
+ args.append(" ");
+ }
+ }
+ if (getClasspath() != null) {
+ args.append("-classpath ");
+ args.append(getClasspath());
+ args.append(" ");
+ }
+ if (getXlintfile() != null) {
+ args.append("-Xlintfile ");
+ args.append(getXlintfile());
+ args.append(" ");
+ }
+ if (getExtdirs() != null) {
+ args.append("-extdirs ");
+ args.append(getExtdirs());
+ args.append(" ");
+ }
+ List fileList = new ArrayList();
+ List jarList = new ArrayList();
+ // convention that any jar on file list should be added to inpath
+ String files = getFiles();
+ if (files == null) files = "";
+ StringTokenizer strTok = new StringTokenizer(files,",");
+ while (strTok.hasMoreTokens()) {
+ String file = strTok.nextToken();
+ if (file.endsWith(".jar")) {
+ jarList.add(file);
+ } else {
+ fileList.add(file);
+ }
+ }
+ if ((getInpath() != null) || !jarList.isEmpty()) {
+ args.append("-inpath ");
+ if (getInpath() != null) args.append(getInpath());
+ for (Iterator iter = jarList.iterator(); iter.hasNext();) {
+ String jar = (String) iter.next();
+ args.append(File.pathSeparator);
+ args.append(jar);
+ }
+ args.append(" ");
+ }
+ for (Iterator iter = fileList.iterator(); iter.hasNext();) {
+ String file = (String) iter.next();
+ args.append(file);
+ args.append(" ");
+ }
+ String argumentString = args.toString();
+ strTok = new StringTokenizer(argumentString," ");
+ String[] ret = new String[strTok.countTokens()];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = strTok.nextToken();
+ }
+ return ret;
+ }
+
+ private AjcTestCase.MessageSpec buildMessageSpec() {
+ List infos = null;
+ List warnings = new ArrayList();
+ List errors = new ArrayList();
+ List fails = new ArrayList();
+ for (Iterator iter = expected.iterator(); iter.hasNext();) {
+ ExpectedMessageSpec exMsg = (ExpectedMessageSpec) iter.next();
+ String kind = exMsg.getKind();
+ if (kind.equals("info")) {
+ if (infos == null) infos = new ArrayList();
+ infos.add(exMsg.toMessage());
+ } else if (kind.equals("warning")) {
+ warnings.add(exMsg.toMessage());
+ } else if (kind.equals("error")) {
+ errors.add(exMsg.toMessage());
+ } else if (kind.equals("fail")) {
+ fails.add(exMsg.toMessage());
+ } else if (kind.equals("abort")) {
+ fails.add(exMsg.toMessage());
+ }
+ }
+ return new AjcTestCase.MessageSpec(infos,warnings,errors,fails);
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer,
+ * ******************************************************************/
+package org.aspectj.testing;
+
+import org.aspectj.tools.ajc.AjcTestCase;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class ExpectedMessageSpec {
+
+ private String kind = "error";
+ private int line = -1;
+ private String text;
+ private String file;
+ private String details;
+
+ public AjcTestCase.Message toMessage() {
+ return new AjcTestCase.Message(line,file,text,null);
+ }
+
+ /**
+ * @return Returns the details.
+ */
+ public String getDetails() {
+ return details;
+ }
+ /**
+ * @param details The details to set.
+ */
+ public void setDetails(String details) {
+ this.details = details;
+ }
+ /**
+ * @return Returns the file.
+ */
+ public String getFile() {
+ return file;
+ }
+ /**
+ * @param file The file to set.
+ */
+ public void setFile(String file) {
+ this.file = file;
+ }
+ /**
+ * @return Returns the kind.
+ */
+ public String getKind() {
+ return kind;
+ }
+ /**
+ * @param kind The kind to set.
+ */
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+ /**
+ * @return Returns the line.
+ */
+ public int getLine() {
+ return line;
+ }
+ /**
+ * @param line The line to set.
+ */
+ public void setLine(int line) {
+ this.line = line;
+ }
+ /**
+ * @return Returns the text.
+ */
+ public String getText() {
+ return text;
+ }
+ /**
+ * @param text The text to set.
+ */
+ public void setText(String text) {
+ this.text = text;
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer,
+ * ******************************************************************/
+package org.aspectj.testing;
+
+import org.aspectj.tools.ajc.AjcTestCase;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public interface ITestStep {
+
+ void execute(AjcTestCase inTestCase);
+
+ void addExpectedMessage(ExpectedMessageSpec message);
+
+ void setBaseDir(String dir);
+
+ void setTest(AjcTest test);
+}
--- /dev/null
+/*
+ * Created on 02-Aug-2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.aspectj.testing;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.digester.Digester;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class MakeTestClass {
+
+ private static final String HEADER =
+ "/* *******************************************************************\n" +
+ " * Copyright (c) 2004 IBM Corporation\n" +
+ " * All rights reserved.\n" +
+ " * This program and the accompanying materials are made available\n" +
+ " * under the terms of the Common Public License v1.0\n" +
+ " * which accompanies this distribution and is available at\n" +
+ " * http://www.eclipse.org/legal/cpl-v10.html \n" +
+ " * \n" +
+ " * ******************************************************************/\n" +
+ "package org.aspectj.systemtest.XXX;\n" +
+ "\n" +
+ "import java.io.File;\n" +
+ "import junit.framework.Test;\n" +
+ "import org.aspectj.testing.XMLBasedAjcTestCase;\n" +
+ "\n" +
+ "public class ";
+
+ private static final String BODY_1 =
+ " extends org.aspectj.testing.XMLBasedAjcTestCase {\n" +
+ "\n" +
+ " public static Test suite() {\n" +
+ " return XMLBasedAjcTestCase.loadSuite(";
+
+ private static final String BODY_2 =
+ ".class);\n" +
+ " }\n" +
+ "\n" +
+ " protected File getSpecFile() {\n" +
+ " return new File(\"";
+
+ private static final String BODY_3 =
+ "\");\n" +
+ " }\n";
+
+ private static final String FOOTER =
+ "}\n";
+
+ private List tests = new ArrayList();
+ private String className;
+ private String suiteFile;
+
+ public static void main(String[] args) throws Exception {
+ new MakeTestClass(args[0],args[1]).makeTestClass();
+ }
+
+ public MakeTestClass(String className, String suiteFile)throws Exception {
+ this.className = className;
+ this.suiteFile = suiteFile;
+ Digester d = getDigester();
+ InputStreamReader isr = new InputStreamReader(new FileInputStream(suiteFile));
+ d.parse(isr);
+ }
+
+ public void addTest(AjcTest test) {
+ tests.add(test);
+ }
+
+ public void makeTestClass() throws Exception {
+ FileOutputStream fos = new FileOutputStream(className + ".java");
+ PrintStream out = new PrintStream(fos);
+ out.print(HEADER);
+ out.print(className);
+ out.print(BODY_1);
+ out.print(className);
+ out.print(BODY_2);
+ out.print(suiteFile);
+ out.print(BODY_3);
+ out.println();
+ int testNo = 1;
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMinimumIntegerDigits(3);
+ for (Iterator iter = tests.iterator(); iter.hasNext();) {
+ AjcTest test = (AjcTest) iter.next();
+ out.println();
+ out.print(" public void test");
+ out.print(nf.format(testNo++));
+ out.println("(){");
+ out.println(" runTest(\"" + test.getTitle() + "\");");
+ out.println(" }");
+ }
+ out.println();
+ out.println(FOOTER);
+ out.close();
+ }
+
+ private Digester getDigester() {
+ Digester digester = new Digester();
+ digester.push(this);
+ digester.addObjectCreate("suite/ajc-test",AjcTest.class);
+ digester.addSetProperties("suite/ajc-test");
+ digester.addSetNext("suite/ajc-test","addTest","org.aspectj.testing.AjcTest");
+ return digester;
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer,
+ * ******************************************************************/
+package org.aspectj.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.aspectj.tools.ajc.AjcTestCase;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class RunSpec implements ITestStep {
+
+ private List expected = new ArrayList();
+ private String classToRun;
+ private String baseDir;
+ private String options;
+ private AjcTest myTest;
+
+ public RunSpec() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.testing.ITestStep#execute(org.aspectj.tools.ajc.AjcTestCase)
+ */
+ public void execute(AjcTestCase inTestCase) {
+ if (!expected.isEmpty()) {
+ System.err.println("Warning, message spec for run command is currently ignored (org.aspectj.testing.RunSpec)");
+ }
+ String[] args = buildArgs();
+ AjcTestCase.RunResult rr = inTestCase.run(getClassToRun(),args,null);
+ }
+
+ public void addExpectedMessage(ExpectedMessageSpec message) {
+ expected.add(message);
+ }
+
+ public void setBaseDir(String dir) {
+ this.baseDir = dir;
+ }
+
+ public void setTest(AjcTest test) {
+ this.myTest = test;
+ }
+
+ public String getOptions() {
+ return options;
+ }
+
+ public void setOptions(String options) {
+ this.options = options;
+ }
+ /**
+ * @return Returns the classToRun.
+ */
+ public String getClassToRun() {
+ return classToRun;
+ }
+ /**
+ * @param classToRun The classToRun to set.
+ */
+ public void setClassToRun(String classToRun) {
+ this.classToRun = classToRun;
+ }
+
+ private String[] buildArgs() {
+ if (options == null) return new String[0];
+ StringTokenizer strTok = new StringTokenizer(options,",");
+ String[] ret = new String[strTok.countTokens()];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = strTok.nextToken();
+ }
+ return ret;
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer,
+ * ******************************************************************/
+package org.aspectj.testing;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.digester.Digester;
+import org.aspectj.tools.ajc.AjcTestCase;
+
+/**
+ * Root class for all Test suites that are based on an AspectJ XML test suite
+ * file. Extends AjcTestCase allowing a mix of programmatic and spec-file
+ * driven testing. See org.aspectj.systemtest.incremental.IncrementalTests for
+ * an example of this mixed style.
+ * <p>The class org.aspectj.testing.MakeTestClass will generate a subclass of
+ * this class for you, given a suite spec. file as input...</p>
+ */
+public abstract class XMLBasedAjcTestCase extends AjcTestCase {
+
+ private static Map testMap = new HashMap();
+ private static boolean suiteLoaded = false;
+ private AjcTest currentTest = null;
+
+ public XMLBasedAjcTestCase() {
+ }
+
+ /**
+ * You must define a suite() method in subclasses, and return
+ * the result of calling this method. (Don't you hate static
+ * methods in programming models). For example:
+ * <pre>
+ * public static Test suite() {
+ * return XMLBasedAjcTestCase.loadSuite(MyTestCaseClass.class);
+ * }
+ * </pre>
+ * @param testCaseClass
+ * @return
+ */
+ public static Test loadSuite(Class testCaseClass) {
+ TestSuite suite = new TestSuite(testCaseClass.getName());
+ suite.addTestSuite(testCaseClass);
+ TestSetup wrapper = new TestSetup(suite) {
+ /* (non-Javadoc)
+ * @see junit.extensions.TestSetup#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ suiteLoaded = false;
+ }
+ /* (non-Javadoc)
+ * @see junit.extensions.TestSetup#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ suiteLoaded = false;
+ }
+ };
+ return wrapper;
+ }
+
+ /**
+ * The file containing the XML specification for the tests.
+ */
+ protected abstract File getSpecFile();
+
+ /*
+ * Return a map from (String) test title -> AjcTest
+ */
+ private Map getSuiteTests() {
+ return testMap;
+ }
+
+ /**
+ * This helper method runs the test with the given title in the
+ * suite spec file. All tests steps in given ajc-test execute
+ * in the same sandbox.
+ */
+ protected void runTest(String title) {
+ currentTest = (AjcTest) testMap.get(title);
+ if (currentTest == null) {
+ fail("No test '" + title + "' in suite.");
+ }
+ ajc.setShouldEmptySandbox(true);
+ currentTest.runTest(this);
+ }
+
+ /**
+ * Get the currently executing test. Useful for access to e.g.
+ * AjcTest.getTitle() etc..
+ */
+ protected AjcTest getCurrentTest() {
+ return currentTest;
+ }
+
+ /**
+ * For use by the Digester. As the XML document is parsed, it creates instances
+ * of AjcTest objects, which are added to this TestCase by the Digester by
+ * calling this method.
+ */
+ public void addTest(AjcTest test) {
+ testMap.put(test.getTitle(),test);
+ }
+
+ /*
+ * The rules for parsing a suite spec file. The Digester using bean properties to match attributes
+ * in the XML document to properties in the associated classes, so this simple implementation should
+ * be very easy to maintain and extend should you ever need to.
+ */
+ private Digester getDigester() {
+ Digester digester = new Digester();
+ digester.push(this);
+ digester.addObjectCreate("suite/ajc-test",AjcTest.class);
+ digester.addSetProperties("suite/ajc-test");
+ digester.addSetNext("suite/ajc-test","addTest","org.aspectj.testing.AjcTest");
+ digester.addObjectCreate("suite/ajc-test/compile",CompileSpec.class);
+ digester.addSetProperties("suite/ajc-test/compile");
+ digester.addSetNext("suite/ajc-test/compile","addTestStep","org.aspectj.testing.ITestStep");
+ digester.addObjectCreate("suite/ajc-test/run",RunSpec.class);
+ digester.addSetProperties("suite/ajc-test/run","class","classToRun");
+ digester.addSetNext("suite/ajc-test/run","addTestStep","org.aspectj.testing.ITestStep");
+ digester.addObjectCreate("*/message",ExpectedMessageSpec.class);
+ digester.addSetProperties("*/message");
+ digester.addSetNext("*/message","addExpectedMessage","org.aspectj.testing.ExpectedMessageSpec");
+ return digester;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.tools.ajc.AjcTestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!suiteLoaded) {
+ testMap = new HashMap();
+ System.out.println("LOADING SUITE: " + getSpecFile().getPath());
+ Digester d = getDigester();
+ try {
+ InputStreamReader isr = new InputStreamReader(new FileInputStream(getSpecFile()));
+ d.parse(isr);
+ } catch (Exception ex) {
+ fail("Unable to load suite " + getSpecFile().getPath() + " : " + ex);
+ }
+ suiteLoaded = true;
+ }
+ }
+}
+