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