1 package fit;
2
3
4
5
6 import java.io.*;
7 import java.util.*;
8 import java.lang.reflect.*;
9 import java.text.DateFormat;
10
11 import net.sourceforge.xmlfit.fit.stepper.gui.DebuggerFrame;
12
13 public class Fixture {
14
15 private static final String FIT_DEBUGMODE = "fit.debugmode";
16 private static boolean debugMode = false;
17
18 static
19 {
20 String property = System.getProperty(FIT_DEBUGMODE);
21 if(property != null && property.equals("true"))
22 {
23 debugMode = true;
24 }
25 }
26
27 public Map summary = new HashMap();
28 public Counts counts = new Counts();
29 protected String[] args;
30
31 public class RunTime {
32 long start = System.currentTimeMillis();
33 long elapsed = 0;
34
35 public String toString() {
36 elapsed = (System.currentTimeMillis()-start);
37 if (elapsed > 600000) {
38 return d(3600000)+":"+d(600000)+d(60000)+":"+d(10000)+d(1000);
39 } else {
40 return d(60000)+":"+d(10000)+d(1000)+"."+d(100)+d(10);
41 }
42 }
43
44 String d(long scale) {
45 long report = elapsed / scale;
46 elapsed -= report * scale;
47 return Long.toString(report);
48 }
49 }
50
51
52
53
54 private static DebuggerFrame frame = new DebuggerFrame();
55
56
57 public void doTables(Parse tables) {
58 if(debugMode)
59 frame.initTabeles(tables);
60
61 summary.put("run date", new Date());
62 summary.put("run elapsed time", new RunTime());
63 if (tables != null) {
64 Parse fixtureName = fixtureName(tables);
65 if (fixtureName != null) {
66 try {
67 Fixture fixture = getLinkedFixtureWithArgs(tables);
68 fixture.interpretTables(tables);
69 } catch (Exception e) {
70 exception (fixtureName, e);
71 interpretFollowingTables(tables);
72 }
73 }
74 }
75 }
76
77
78 protected void interpretTables(Parse tables) {
79 try {
80 getArgsForTable(tables);
81 doTable(tables);
82 } catch (Exception ex) {
83 exception(fixtureName(tables), ex);
84 return;
85 }
86 interpretFollowingTables(tables);
87 }
88
89
90 private void interpretFollowingTables(Parse tables) {
91
92 tables = tables.more;
93 while (tables != null) {
94 Parse fixtureName = fixtureName(tables);
95 if (fixtureName != null) {
96 try {
97 Fixture fixture = getLinkedFixtureWithArgs(tables);
98 fixture.doTable(tables);
99 } catch (Throwable e) {
100 exception(fixtureName, e);
101 }
102 }
103
104 tables = tables.more;
105 }
106 }
107
108
109 protected Fixture getLinkedFixtureWithArgs(Parse tables) throws Exception {
110 Parse header = tables.at(0, 0, 0);
111 Fixture fixture = loadFixture(header.text());
112 fixture.counts = counts;
113 fixture.summary = summary;
114 fixture.getArgsForTable(tables);
115 return fixture;
116 }
117
118 public Parse fixtureName(Parse tables) {
119 return tables.at(0, 0, 0);
120 }
121
122 public Fixture loadFixture(String fixtureName)
123 throws InstantiationException, IllegalAccessException {
124 String notFound = "The fixture \"" + fixtureName + "\" was not found.";
125 try {
126 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
127 Class<?> fixtureClass = contextClassLoader.loadClass(fixtureName);
128 return (Fixture) fixtureClass.newInstance();
129 }
130 catch (ClassCastException e) {
131 throw new RuntimeException("\"" + fixtureName + "\" was found, but it's not a fixture.", e);
132 }
133 catch (ClassNotFoundException e) {
134 throw new RuntimeException(notFound, e);
135 }
136 catch (NoClassDefFoundError e) {
137 throw new RuntimeException(notFound, e);
138 }
139 }
140
141
142 protected void getArgsForTable(Parse table) {
143 ArrayList argumentList = new ArrayList();
144 Parse parameters = table.parts.parts.more;
145 for (; parameters != null; parameters = parameters.more)
146 argumentList.add(parameters.text());
147 args = (String[]) argumentList.toArray(new String[0]);
148 }
149
150 public void doTable(Parse table) {
151 doRows(table.parts.more);
152 }
153
154 public void doRows(Parse rows) {
155 while (rows != null) {
156 Parse more = rows.more;
157 doRow(rows);
158 rows = more;
159 }
160 }
161
162 public void doRow(Parse row) {
163 if(debugMode)
164 frame.doRow(row.parts);
165 doCells(row.parts);
166 }
167
168 public void doCells(Parse cells) {
169 for (int i=0; cells != null; i++) {
170 try {
171 doCell(cells, i);
172 } catch (Exception e) {
173 exception(cells, e);
174 }
175 cells=cells.more;
176 }
177 }
178
179 public void doCell(Parse cell, int columnNumber) {
180 ignore(cell);
181 }
182
183
184
185
186 public static String green = "#cfffcf";
187 public static String red = "#ffcfcf";
188 public static String gray = "#efefef";
189 public static String yellow = "#ffffcf";
190
191 public void right (Parse cell) {
192 cell.addToTag(" bgcolor=\"" + green + "\"");
193 counts.right++;
194 }
195
196 public void wrong (Parse cell) {
197 cell.addToTag(" bgcolor=\"" + red + "\"");
198 cell.body = escape(cell.text());
199 counts.wrong++;
200 }
201
202 public void wrong (Parse cell, String actual) {
203 wrong(cell);
204 cell.addToBody(label("expected") + "<hr>" + escape(actual) + label("actual"));
205 }
206
207 public void info (Parse cell, String message) {
208 cell.addToBody(info(message));
209 }
210
211 public String info (String message) {
212 return " <font color=\"#808080\">" + escape(message) + "</font>";
213 }
214
215 public void ignore (Parse cell) {
216 cell.addToTag(" bgcolor=\"" + gray + "\"");
217 counts.ignores++;
218 }
219
220 public void error (Parse cell, String message) {
221 cell.body = escape(cell.text());
222 cell.addToBody("<hr><pre>" + escape(message) + "</pre>");
223 cell.addToTag(" bgcolor=\"" + yellow + "\"");
224 counts.exceptions++;
225 }
226
227 public void exception (Parse cell, Throwable exception) {
228 while(exception.getClass().equals(InvocationTargetException.class)) {
229 exception = ((InvocationTargetException)exception).getTargetException();
230 }
231 final StringWriter buf = new StringWriter();
232 exception.printStackTrace(new PrintWriter(buf));
233 error(cell, buf.toString());
234 }
235
236
237
238 public String counts() {
239 return counts.toString();
240 }
241
242 public static String label (String string) {
243 return " <font size=-1 color=\"#c08080\"><i>" + string + "</i></font>";
244 }
245
246 public static String escape (String string) {
247 string = string.replaceAll("&", "&");
248 string = string.replaceAll("<", "<");
249 string = string.replaceAll(" ", " ");
250 string = string.replaceAll("\r\n", "<br />");
251 string = string.replaceAll("\r", "<br />");
252 string = string.replaceAll("\n", "<br />");
253 return string;
254 }
255
256 public static String camel (String name) {
257 StringBuffer b = new StringBuffer(name.length());
258 StringTokenizer t = new StringTokenizer(name);
259 if (!t.hasMoreTokens())
260 return name;
261 b.append(t.nextToken());
262 while (t.hasMoreTokens()) {
263 String token = t.nextToken();
264 b.append(token.substring(0, 1).toUpperCase());
265 b.append(token.substring(1));
266 }
267 return b.toString();
268 }
269
270 public Object parse (String s, Class type) throws Exception {
271 if (type.equals(String.class)) {return s;}
272 if (type.equals(Date.class)) {return DateFormat.getDateInstance().parse(s);}
273 if (type.equals(ScientificDouble.class)) {return ScientificDouble.valueOf(s);}
274 throw new Exception("can't yet parse "+type);
275 }
276
277 public void check(Parse cell, TypeAdapter a) {
278 String text = cell.text();
279 if (text.equals("")) {
280 try {
281 info(cell, a.toString(a.get()));
282 } catch (Exception e) {
283 info(cell, "error");
284 }
285 } else if (a == null) {
286 ignore(cell);
287 } else if (text.equals("error")) {
288 try {
289 Object result = a.invoke();
290 wrong(cell, a.toString(result));
291 } catch (IllegalAccessException e) {
292 exception (cell, e);
293 } catch (Exception e) {
294 right(cell);
295 }
296 } else {
297 try {
298 Object result = a.get();
299 if (a.equals(a.parse(text), result)) {
300 right(cell);
301 } else {
302 wrong(cell, a.toString(result));
303 }
304 } catch (Exception e) {
305 exception(cell, e);
306 }
307 }
308 }
309
310
311 public String[] getArgs() {
312 return args;
313 }
314
315 }