001: package fit;
002:
003: // Copyright (c) 2002-2005 Cunningham & Cunningham, Inc.
004: // Released under the terms of the GNU General Public License version 2 or later.
005:
006: import java.io.*;
007: import java.util.*;
008: import java.lang.reflect.*;
009: import java.text.DateFormat;
010:
011: public class Fixture {
012:
013: public Map summary = new HashMap();
014: public Counts counts = new Counts();
015: protected String[] args;
016:
017: public class RunTime {
018: long start = System.currentTimeMillis();
019: long elapsed = 0;
020:
021: public String toString() {
022: elapsed = (System.currentTimeMillis() - start);
023: if (elapsed > 600000) {
024: return d(3600000) + ":" + d(600000) + d(60000) + ":"
025: + d(10000) + d(1000);
026: } else {
027: return d(60000) + ":" + d(10000) + d(1000) + "."
028: + d(100) + d(10);
029: }
030: }
031:
032: String d(long scale) {
033: long report = elapsed / scale;
034: elapsed -= report * scale;
035: return Long.toString(report);
036: }
037: }
038:
039: // Traversal //////////////////////////
040:
041: /* Altered by Rick Mugridge to dispatch on the first Fixture */
042: public void doTables(Parse tables) {
043: summary.put("run date", new Date());
044: summary.put("run elapsed time", new RunTime());
045: if (tables != null) {
046: Parse fixtureName = fixtureName(tables);
047: if (fixtureName != null) {
048: try {
049: Fixture fixture = getLinkedFixtureWithArgs(tables);
050: fixture.interpretTables(tables);
051: } catch (Exception e) {
052: exception(fixtureName, e);
053: interpretFollowingTables(tables);
054: }
055: }
056: }
057: }
058:
059: /* Added by Rick Mugridge to allow a dispatch into DoFixture */
060: protected void interpretTables(Parse tables) {
061: try { // Don't create the first fixture again, because creation may do something important.
062: getArgsForTable(tables); // get them again for the new fixture object
063: doTable(tables);
064: } catch (Exception ex) {
065: exception(fixtureName(tables), ex);
066: return;
067: }
068: interpretFollowingTables(tables);
069: }
070:
071: /* Added by Rick Mugridge */
072: private void interpretFollowingTables(Parse tables) {
073: //listener.tableFinished(tables);
074: tables = tables.more;
075: while (tables != null) {
076: Parse fixtureName = fixtureName(tables);
077: if (fixtureName != null) {
078: try {
079: Fixture fixture = getLinkedFixtureWithArgs(tables);
080: fixture.doTable(tables);
081: } catch (Throwable e) {
082: exception(fixtureName, e);
083: }
084: }
085: //listener.tableFinished(tables);
086: tables = tables.more;
087: }
088: }
089:
090: /* Added from FitNesse*/
091: protected Fixture getLinkedFixtureWithArgs(Parse tables)
092: throws Exception {
093: Parse header = tables.at(0, 0, 0);
094: Fixture fixture = loadFixture(header.text());
095: fixture.counts = counts;
096: fixture.summary = summary;
097: fixture.getArgsForTable(tables);
098: return fixture;
099: }
100:
101: public Parse fixtureName(Parse tables) {
102: return tables.at(0, 0, 0);
103: }
104:
105: public Fixture loadFixture(String fixtureName)
106: throws InstantiationException, IllegalAccessException {
107: String notFound = "The fixture \"" + fixtureName
108: + "\" was not found.";
109: try {
110: return (Fixture) (Class.forName(fixtureName).newInstance());
111: } catch (ClassCastException e) {
112: throw new RuntimeException("\"" + fixtureName
113: + "\" was found, but it's not a fixture.", e);
114: } catch (ClassNotFoundException e) {
115: throw new RuntimeException(notFound, e);
116: } catch (NoClassDefFoundError e) {
117: throw new RuntimeException(notFound, e);
118: }
119: }
120:
121: /* Added by Rick Mugridge, from FitNesse */
122: protected void getArgsForTable(Parse table) {
123: ArrayList argumentList = new ArrayList();
124: Parse parameters = table.parts.parts.more;
125: for (; parameters != null; parameters = parameters.more)
126: argumentList.add(parameters.text());
127: args = (String[]) argumentList.toArray(new String[0]);
128: }
129:
130: public void doTable(Parse table) {
131: doRows(table.parts.more);
132: }
133:
134: public void doRows(Parse rows) {
135: while (rows != null) {
136: Parse more = rows.more;
137: doRow(rows);
138: rows = more;
139: }
140: }
141:
142: public void doRow(Parse row) {
143: doCells(row.parts);
144: }
145:
146: public void doCells(Parse cells) {
147: for (int i = 0; cells != null; i++) {
148: try {
149: doCell(cells, i);
150: } catch (Exception e) {
151: exception(cells, e);
152: }
153: cells = cells.more;
154: }
155: }
156:
157: public void doCell(Parse cell, int columnNumber) {
158: ignore(cell);
159: }
160:
161: // Annotation ///////////////////////////////
162:
163: public static String green = "#cfffcf";
164: public static String red = "#ffcfcf";
165: public static String gray = "#efefef";
166: public static String yellow = "#ffffcf";
167:
168: public void right(Parse cell) {
169: cell.addToTag(" bgcolor=\"" + green + "\"");
170: counts.right++;
171: }
172:
173: public void wrong(Parse cell) {
174: cell.addToTag(" bgcolor=\"" + red + "\"");
175: cell.body = escape(cell.text());
176: counts.wrong++;
177: }
178:
179: public void wrong(Parse cell, String actual) {
180: wrong(cell);
181: cell.addToBody(label("expected") + "<hr>" + escape(actual)
182: + label("actual"));
183: }
184:
185: public void info(Parse cell, String message) {
186: cell.addToBody(info(message));
187: }
188:
189: public String info(String message) {
190: return " <font color=\"#808080\">" + escape(message)
191: + "</font>";
192: }
193:
194: public void ignore(Parse cell) {
195: cell.addToTag(" bgcolor=\"" + gray + "\"");
196: counts.ignores++;
197: }
198:
199: public void error(Parse cell, String message) {
200: cell.body = escape(cell.text());
201: cell.addToBody("<hr><pre>" + escape(message) + "</pre>");
202: cell.addToTag(" bgcolor=\"" + yellow + "\"");
203: counts.exceptions++;
204: }
205:
206: public void exception(Parse cell, Throwable exception) {
207: while (exception.getClass().equals(
208: InvocationTargetException.class)) {
209: exception = ((InvocationTargetException) exception)
210: .getTargetException();
211: }
212: final StringWriter buf = new StringWriter();
213: exception.printStackTrace(new PrintWriter(buf));
214: error(cell, buf.toString());
215: }
216:
217: // Utility //////////////////////////////////
218:
219: public String counts() {
220: return counts.toString();
221: }
222:
223: public static String label(String string) {
224: return " <font size=-1 color=\"#c08080\"><i>" + string
225: + "</i></font>";
226: }
227:
228: public static String escape(String string) {
229: string = string.replaceAll("&", "&");
230: string = string.replaceAll("<", "<");
231: string = string.replaceAll(" ", " ");
232: string = string.replaceAll("\r\n", "<br />");
233: string = string.replaceAll("\r", "<br />");
234: string = string.replaceAll("\n", "<br />");
235: return string;
236: }
237:
238: public static String camel(String name) {
239: StringBuffer b = new StringBuffer(name.length());
240: StringTokenizer t = new StringTokenizer(name);
241: if (!t.hasMoreTokens())
242: return name;
243: b.append(t.nextToken());
244: while (t.hasMoreTokens()) {
245: String token = t.nextToken();
246: b.append(token.substring(0, 1).toUpperCase()); // replace spaces with camelCase
247: b.append(token.substring(1));
248: }
249: return b.toString();
250: }
251:
252: public Object parse(String s, Class type) throws Exception {
253: if (type.equals(String.class)) {
254: return s;
255: }
256: if (type.equals(Date.class)) {
257: return DateFormat.getDateInstance().parse(s);
258: }
259: if (type.equals(ScientificDouble.class)) {
260: return ScientificDouble.valueOf(s);
261: }
262: throw new Exception("can't yet parse " + type);
263: }
264:
265: public void check(Parse cell, TypeAdapter a) {
266: String text = cell.text();
267: if (text.equals("")) {
268: try {
269: info(cell, a.toString(a.get()));
270: } catch (Exception e) {
271: info(cell, "error");
272: }
273: } else if (a == null) {
274: ignore(cell);
275: } else if (text.equals("error")) {
276: try {
277: Object result = a.invoke();
278: wrong(cell, a.toString(result));
279: } catch (IllegalAccessException e) {
280: exception(cell, e);
281: } catch (Exception e) {
282: right(cell);
283: }
284: } else {
285: try {
286: Object result = a.get();
287: if (a.equals(a.parse(text), result)) {
288: right(cell);
289: } else {
290: wrong(cell, a.toString(result));
291: }
292: } catch (Exception e) {
293: exception(cell, e);
294: }
295: }
296: }
297:
298: /* Added by Rick, from FitNesse */
299: public String[] getArgs() {
300: return args;
301: }
302:
303: }
|