001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.runner;
004:
005: import fit.*;
006: import java.util.*;
007: import java.io.*;
008: import java.net.*;
009: import java.lang.reflect.Method;
010: import fitnesse.components.CommandLine;
011:
012: public class TestRunner {
013: private String host;
014: private int port;
015: private String pageName;
016: private FitServer fitServer;
017: public TestRunnerFixtureListener fixtureListener;
018: public CachingResultFormatter handler;
019: private PrintStream output;
020: public List<FormattingOption> formatters = new LinkedList<FormattingOption>();
021: private boolean debug;
022: public boolean verbose;
023: public boolean usingDownloadedPaths = true;
024: private String suiteFilter = null;
025:
026: public TestRunner() throws Exception {
027: this (System.out);
028: }
029:
030: public TestRunner(PrintStream output) throws Exception {
031: this .output = output;
032: handler = new CachingResultFormatter();
033: }
034:
035: public static void main(String[] args) throws Exception {
036: TestRunner runner = new TestRunner();
037: runner.run(args);
038: System.exit(runner.exitCode());
039: }
040:
041: public void args(String[] args) throws Exception {
042: CommandLine commandLine = new CommandLine(
043: "[-debug] [-v] [-results file] [-html file] [-xml file] [-nopath] [-suiteFilter filter] host port pageName");
044: if (!commandLine.parse(args))
045: usage();
046:
047: host = commandLine.getArgument("host");
048: port = Integer.parseInt(commandLine.getArgument("port"));
049: pageName = commandLine.getArgument("pageName");
050:
051: if (commandLine.hasOption("debug"))
052: debug = true;
053: if (commandLine.hasOption("v")) {
054: verbose = true;
055: handler.addHandler(new StandardResultHandler(output));
056: }
057: if (commandLine.hasOption("nopath"))
058: usingDownloadedPaths = false;
059: if (commandLine.hasOption("results"))
060: formatters.add(new FormattingOption("raw", commandLine
061: .getOptionArgument("results", "file"), output,
062: host, port, pageName));
063: if (commandLine.hasOption("html"))
064: formatters.add(new FormattingOption("html", commandLine
065: .getOptionArgument("html", "file"), output, host,
066: port, pageName));
067: if (commandLine.hasOption("xml"))
068: formatters.add(new FormattingOption("xml", commandLine
069: .getOptionArgument("xml", "file"), output, host,
070: port, pageName));
071:
072: if (commandLine.hasOption("suiteFilter"))
073: suiteFilter = commandLine.getOptionArgument("suiteFilter",
074: "filter");
075: }
076:
077: private void usage() {
078: System.out
079: .println("usage: java fitnesse.runner.TestRunner [options] host port page-name");
080: System.out
081: .println("\t-v \tverbose: prints test progress to stdout");
082: System.out
083: .println("\t-results <filename|'stdout'>\tsave raw test results to a file or dump to standard output");
084: System.out
085: .println("\t-html <filename|'stdout'>\tformat results as HTML and save to a file or dump to standard output");
086: System.out
087: .println("\t-debug \tprints FitServer protocol actions to stdout");
088: System.out
089: .println("\t-nopath \tprevents downloaded path elements from being added to classpath");
090: System.exit(-1);
091: }
092:
093: public void run(String[] args) throws Exception {
094: args(args);
095: fitServer = new FitServer(host, port, debug);
096: fixtureListener = new TestRunnerFixtureListener(this );
097: fitServer.fixtureListener = fixtureListener;
098: fitServer.establishConnection(makeHttpRequest());
099: fitServer.validateConnection();
100: if (usingDownloadedPaths)
101: processClasspathDocument();
102: fitServer.process();
103: finalCount();
104: fitServer.closeConnection();
105: fitServer.exit();
106: doFormatting();
107: handler.cleanUp();
108: }
109:
110: private void processClasspathDocument() throws Exception {
111: String classpathItems = fitServer.readDocument();
112: if (verbose)
113: output.println("Adding to classpath: " + classpathItems);
114: addItemsToClasspath(classpathItems);
115: }
116:
117: private void finalCount() throws Exception {
118: handler.acceptFinalCount(fitServer.getCounts());
119: }
120:
121: public int exitCode() {
122: return fitServer == null ? -1 : fitServer.exitCode();
123: }
124:
125: public String makeHttpRequest() {
126: String request = "GET /" + pageName + "?responder=fitClient";
127: if (usingDownloadedPaths)
128: request += "&includePaths=yes";
129: if (suiteFilter != null) {
130: request += "&suiteFilter=" + suiteFilter;
131: }
132: return request + " HTTP/1.1\r\n\r\n";
133: }
134:
135: public Counts getCounts() {
136: return fitServer.getCounts();
137: }
138:
139: public void acceptResults(PageResult results) throws Exception {
140: Counts counts = results.counts();
141: fitServer.writeCounts(counts);
142: handler.acceptResult(results);
143: }
144:
145: public void doFormatting() throws Exception {
146: for (Iterator iterator = formatters.iterator(); iterator
147: .hasNext();) {
148: FormattingOption option = (FormattingOption) iterator
149: .next();
150: if (verbose)
151: output.println("Formatting as " + option.format
152: + " to " + option.filename);
153: option.process(handler.getResultStream(), handler
154: .getByteCount());
155: }
156: }
157:
158: public static void addItemsToClasspath(String classpathItems)
159: throws Exception {
160: String[] items = classpathItems.split(System
161: .getProperty("path.separator"));
162: for (int i = 0; i < items.length; i++) {
163: String item = items[i];
164: addUrlToClasspath(new File(item).toURL());
165: }
166: }
167:
168: public static void addUrlToClasspath(URL u) throws Exception {
169: URLClassLoader sysloader = (URLClassLoader) ClassLoader
170: .getSystemClassLoader();
171: Class sysclass = URLClassLoader.class;
172: Method method = sysclass.getDeclaredMethod("addURL",
173: new Class[] { URL.class });
174: method.setAccessible(true);
175: method.invoke(sysloader, new Object[] { u });
176: }
177: }
|