001: /* Textui.java */
002:
003: package org.quilt.textui;
004:
005: import java.io.File;
006: import java.io.FileInputStream;
007: import java.io.IOException;
008: import java.util.Enumeration;
009: import java.util.Hashtable;
010: import java.util.Properties;
011: import java.util.Vector;
012:
013: // XXX remove me
014: import org.apache.tools.ant.BuildException;
015: import org.apache.tools.ant.Project;
016:
017: import org.quilt.cl.QuiltClassLoader;
018: import org.quilt.cover.stmt.StmtRegistry;
019: import org.quilt.framework.QuiltTest;
020: import org.quilt.reports.*;
021: import org.quilt.runner.*;
022:
023: /**
024: * Template textui test runner. Need to add main() and runWithIt().
025: *
026: * @todo Modify to permit types (brief, plain, summary, xml) on the
027: * command line.
028: */
029:
030: public abstract class Textui implements RunnerConst {
031:
032: protected QuiltClassLoader quiltLoader = null;
033:
034: protected StmtRegistry stmtReg = null;
035:
036: // //////////////////////////////////////////////////////////////
037: // NEEDS WORK
038: // //////////////////////////////////////////////////////////////
039:
040: /**
041: * Command line usage message.
042: *
043: * XXX This must be fleshed out.
044: */
045: public void usage() {
046: System.out
047: .println("usage:\n"
048: + "java [javaOptions] testName [testOptions]\n"
049: + "where the test options (all optional) are\n"
050: + " checkCoverage={true|false}\n"
051: + " checkIncludes={comma-separated list of class names}\n"
052: + " checkExcludes={comma-separated list of class names}\n"
053: + " haltOnError={true|false}\n"
054: + " haltOnFailure={true|false}\n"
055: + " filtertrace={true|false}\n"
056: + " formatter={className[,outputName]}\n"
057: + " propsfile={pathname}\n"
058: + " showOutput={true|false}\n"
059: + "Parameter values are not quoted. Anything in square brackets []\n"
060: + "is optional. Anything in curly braces {} is required.\n"
061: + "\n");
062: System.exit(ERRORS);
063: }
064:
065: // YOU MUST IMPLEMENT A main() LIKE THIS:
066: // public static void main(String[] args) throws IOException {
067: // System.exit( new MockTestRunner().handleArgs(args) );
068: // }
069:
070: /**
071: * Called by main - pulls arguments off a command line to build a
072: * QuiltTest structure and formatter vector.
073: *
074: * @see QuiltTest
075: * @see RunnerConst
076: * @param args Usual command line argument vector
077: * @return RunnerConst status codes
078: */
079: protected int handleArgs(String[] args) {
080: int retCode = ERRORS;
081: try {
082: Vector myFormatters = new Vector();
083: if (args.length == 0) {
084: usage();
085: }
086: // our goal here is to populate this structure
087: QuiltTest qt = new QuiltTest(args[0]);
088: qt.setFork(true); // always true if textui
089:
090: Properties p = new Properties();
091: for (int i = 1; i < args.length; i++) {
092: if (args[i].startsWith("checkCoverage=")) {
093: qt.setCheckCoverage(Project.toBoolean(args[i]
094: .substring(14)));
095: } else if (args[i].startsWith("checkExcludes=")) {
096: qt.setCheckExcludes(args[i].substring(14));
097: } else if (args[i].startsWith("checkIncludes=")) {
098: qt.setCheckIncludes(args[i].substring(14));
099: } else if (args[i].startsWith("haltOnError=")) {
100: qt.setHaltOnError(Project.toBoolean(args[i]
101: .substring(12)));
102: } else if (args[i].startsWith("haltOnFailure=")) {
103: qt.setHaltOnFailure(Project.toBoolean(args[i]
104: .substring(14)));
105: } else if (args[i].startsWith("filtertrace=")) {
106: qt.setFiltertrace(Project.toBoolean(args[i]
107: .substring(12)));
108: } else if (args[i].startsWith("formatter=")) {
109: // looks like: "formatter=CLASSNAME{.OUTFILENAME}"
110:
111: // //////////////////////////////////////////////
112: // MODIFY TO PERMIT TYPES (brief, plain, summary, xml)
113: // AS WELL AS CLASS NAMES
114: // //////////////////////////////////////////////
115: try {
116: String selector = args[i].substring(10);
117: int commaAt = selector.indexOf(',');
118: FmtSelector fs = new FmtSelector();
119: if (commaAt < 0) {
120: fs.setClassname(selector);
121: } else {
122: fs.setClassname(selector.substring(0,
123: commaAt));
124: fs.setOutfile(new File(selector
125: .substring(commaAt + 1)));
126: }
127: myFormatters.addElement(fs);
128: } catch (BuildException be) {
129: System.err.println(be.getMessage());
130: System.exit(ERRORS);
131: }
132: } else if (args[i].startsWith("propsfile=")) {
133: FileInputStream in = new FileInputStream(args[i]
134: .substring(10));
135: p.load(in);
136: in.close();
137: } else if (args[i].startsWith("showoutput=")) {
138: qt.setShowOutput(Project.toBoolean(args[i]
139: .substring(11)));
140: }
141: }
142: Hashtable sysP = System.getProperties();
143: Enumeration e = sysP.keys();
144: while (e.hasMoreElements()) {
145: String key = (String) e.nextElement();
146: p.put(key, (String) sysP.get(key));
147: }
148: qt.setProperties(p);
149: // set up QuiltClassLoader if appropriate
150: // // DEBUG
151: // StringBuffer sb = new StringBuffer().append("Textui.handleArgs\n");
152: // String [] inc = qt.getCheckIncludesArray();
153: // sb.append(" includes\n");
154: // for (int j = 0; j < inc.length; j++)
155: // sb.append(" ").append(inc[j]).append("\n");
156:
157: // String [] exc = qt.getCheckExcludesArray();
158: // sb.append(" excludes\n");
159: // for (int j = 0; j < exc.length; j++)
160: // sb.append(" ").append(exc[j]).append("\n");
161: // System.out.println(sb.toString());
162: // // END
163:
164: if (qt.getCheckCoverage()
165: && (qt.getCheckIncludes() != null)) {
166: String myClasspath = System
167: .getProperty("java.class.path");
168: // // DEBUG
169: // System.out.println(
170: // "Textui.handleArgs: setting up QCL with classpath:\n"
171: // + myClasspath);
172: // // END
173: quiltLoader = new QuiltClassLoader(QuiltClassLoader
174: .cpToURLs(myClasspath), (ClassLoader) null, // classloader we delegate to
175: (String[]) null, // delegated classes
176: qt.getCheckIncludesArray(), // needs to be String[]
177: qt.getCheckExcludesArray()); // ditto
178:
179: stmtReg = (StmtRegistry) quiltLoader
180: .addQuiltRegistry("org.quilt.cover.stmt.StmtRegistry");
181: }
182: // // DEBUG
183: // else {
184: // System.out.println("Textui.handleArgs: NOT USING QCL"
185: // + "\n getCheckCoverage() => " + qt.getCheckCoverage());
186: // }
187: // // END
188:
189: retCode = runWithIt(qt, myFormatters);
190: } catch (Exception e) {
191: System.out.println("EXCEPTION " + e);
192: e.printStackTrace();
193: retCode = ERRORS;
194: }
195: return retCode;
196: }
197:
198: /**
199: * Override this method. Runs the individual test.
200: * @param qt Quilt test descriptor
201: * @param myFormatters Vector of formatters
202: */
203: int runWithIt(QuiltTest qt, Vector myFormatters) {
204: // override this; MockTestRunner should be talkative
205: System.out
206: .println("Textui.runWithIt: you should never see this message");
207: return ERRORS;
208: }
209: }
|