1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.jameleon.ui;
20
21 import net.sf.jameleon.LocationAwareTagSupport;
22 import net.sf.jameleon.TestCaseTag;
23 import net.sf.jameleon.data.DataDrivable;
24 import net.sf.jameleon.event.*;
25 import net.sf.jameleon.function.FunctionTag;
26 import net.sf.jameleon.result.DataDrivableRowResult;
27 import net.sf.jameleon.result.FunctionResult;
28 import net.sf.jameleon.result.JameleonTestResult;
29 import net.sf.jameleon.result.TestCaseResult;
30 import net.sf.jameleon.util.JameleonUtility;
31 import org.apache.commons.jelly.LocationAware;
32
33 import javax.swing.*;
34 import javax.swing.event.ListSelectionEvent;
35 import javax.swing.event.ListSelectionListener;
36 import javax.swing.table.DefaultTableModel;
37 import javax.swing.text.BadLocationException;
38 import java.awt.*;
39 import java.awt.event.MouseAdapter;
40 import java.awt.event.MouseEvent;
41 import java.io.File;
42 import java.net.URI;
43 import java.net.URL;
44 import java.text.NumberFormat;
45 import java.util.*;
46 import java.util.List;
47
48 public class TestCaseResultsPane extends JSplitPane implements TestCaseListener,
49 FunctionListener,
50 DataDrivableListener{
51 private static final long serialVersionUID = 1L;
52 protected DefaultTableModel tcModel, tcReasonModel;
53 protected JTable tcTable, tcReasonTable;
54 protected Map testCases = new HashMap();
55 private static final int TC_NUM = 0;
56 private static final int STATUS = 1;
57 private static final int TEST_CASE = 2;
58 private static final int EXEC_TIME = 3;
59 private static final int RUN = 4;
60 private static final int FAIL = 5;
61 private static final int PASS = 6;
62 private static final int TC = 7;
63 protected ImageIcon passedImg, failedImg, runningImg, snapShotImg;
64 private List results = new ArrayList();
65 private JTextArea stackTrace = new JTextArea();
66 private TestCaseTree tcTree;
67 private JTextArea sourceArea;
68 private JFrame rootFrame;
69 private boolean stepNextTag;
70 private boolean debug;
71 private boolean stopExecution;
72 private BasicHtmlBrowser snapShotBrowser = new BasicHtmlBrowser("Snapshot of Error");
73
74 public TestCaseResultsPane(JFrame rootFrame) {
75 super(JSplitPane.VERTICAL_SPLIT);
76 this.rootFrame = rootFrame;
77 setResizeWeight(0.5);
78 setDividerSize(4);
79 initResultsTable();
80 initIcons();
81 }
82
83 protected void setSourceArea(JTextArea sourceArea){
84 this.sourceArea = sourceArea;
85 }
86
87 protected void setTestCaseTree(TestCaseTree tcTree){
88 this.tcTree = tcTree;
89 }
90
91 private void initIcons() {
92 passedImg = createImageIcon("/icons/passed.gif", "Test Passed");
93 failedImg = createImageIcon("/icons/failed.gif", "Test Failed");
94 runningImg = createImageIcon("/icons/running.gif", "Test Running");
95 snapShotImg = createImageIcon("/icons/snapShot.gif", "View Snapshot of Application at Failure Time");
96 }
97
98 public void stopExecution(){
99 this.stopExecution = true;
100 }
101
102 public void proceedExecution(){
103 this.stopExecution = false;
104 }
105
106 public void setDebug(boolean debug){
107 this.debug = debug;
108 }
109
110 protected void setStepNextTag(boolean stepNextTag){
111 this.stepNextTag = stepNextTag;
112 }
113
114 private String convertObjectToToolTip(Object obj){
115 String tip = null;
116 if (obj != null){
117 if (obj instanceof ImageIcon) {
118 tip = ((ImageIcon)obj).getDescription();
119 } else {
120 tip = obj.toString();
121 }
122 }
123 return tip;
124
125 }
126
127 private void initResultsTable() {
128 tcModel = new DefaultTableModel(new Object[]{"#","Status","Test Case","Execution Time"," Run","Fail","Pass","."},0) {
129 public Class getColumnClass(int columnIndex) {
130 Class dataType = super.getColumnClass(columnIndex);
131 if (columnIndex == STATUS) {
132 dataType = Icon.class;
133 }
134 return dataType;
135 }
136 };
137 tcTable = new SortableJTable(new TableSorter(tcModel)) {
138 public String getToolTipText(MouseEvent e) {
139 Point p = e.getPoint();
140 int rowIndex = rowAtPoint(p);
141 int colIndex = columnAtPoint(p);
142 return convertObjectToToolTip(getValueAt(rowIndex, colIndex));
143 }
144
145 };
146 tcTable.setColumnSelectionAllowed(false);
147 tcTable.getColumnModel().getColumn(TEST_CASE).setPreferredWidth(200);
148 tcTable.getColumnModel().getColumn(STATUS).setPreferredWidth(40);
149 tcTable.getColumnModel().getColumn(STATUS).setMaxWidth(40);
150 tcTable.getColumnModel().getColumn(TC_NUM).setPreferredWidth(30);
151 tcTable.getColumnModel().getColumn(TC_NUM).setMaxWidth(30);
152 tcTable.getColumnModel().getColumn(RUN).setPreferredWidth(30);
153 tcTable.getColumnModel().getColumn(RUN).setMaxWidth(30);
154 tcTable.getColumnModel().getColumn(FAIL).setPreferredWidth(30);
155 tcTable.getColumnModel().getColumn(FAIL).setMaxWidth(30);
156 tcTable.getColumnModel().getColumn(PASS).setPreferredWidth(40);
157 tcTable.getColumnModel().getColumn(PASS).setMaxWidth(40);
158 tcTable.getColumnModel().getColumn(EXEC_TIME).setPreferredWidth(100);
159 tcTable.getColumnModel().getColumn(EXEC_TIME).setMaxWidth(100);
160 tcTable.getColumnModel().getColumn(TC).setPreferredWidth(0);
161 tcTable.getColumnModel().getColumn(TC).setMaxWidth(0);
162 tcTable.getSelectionModel().addListSelectionListener(new TCResultsSelectionListeners());
163 tcTable.addMouseListener(new TCResultsMouseListener());
164
165
166 tcReasonModel = new DefaultTableModel(new Object[]{"Row", "Line", " ", "Function Id", "Failed Reason","."},0) {
167 public Class getColumnClass(int columnIndex) {
168 Class dataType = super.getColumnClass(columnIndex);
169 if (columnIndex == TCResultsSelectionListeners.URL) {
170 dataType = Icon.class;
171 }
172 return dataType;
173 }
174 };
175 tcReasonTable = new SortableJTable(new TableSorter(tcReasonModel)){
176 public String getToolTipText(MouseEvent e) {
177 Point p = e.getPoint();
178 int rowIndex = rowAtPoint(p);
179 int colIndex = columnAtPoint(p);
180 return convertObjectToToolTip(getValueAt(rowIndex, colIndex));
181 }
182 };
183
184 tcReasonTable.addMouseListener(new FTResultsMouseListener());
185
186 tcReasonTable.getColumn("Row").setMaxWidth(40);
187 tcReasonTable.getColumn("Line").setMaxWidth(40);
188 tcReasonTable.getColumn(".").setMaxWidth(0);
189 tcReasonTable.getColumn(" ").setMaxWidth(20);
190 tcReasonTable.setColumnSelectionAllowed(false);
191 tcReasonTable.getSelectionModel().addListSelectionListener(new FTResultsSelectionListeners());
192 setTopComponent(new JScrollPane(tcTable));
193 JPanel panel = new JPanel(new SpringLayout());
194 panel.add(new JScrollPane(tcReasonTable));
195 stackTrace.setEditable(false);
196 stackTrace.setLineWrap(false);
197 stackTrace.setRows(20);
198 panel.add(new JScrollPane(stackTrace));
199 SpringUtilities.makeCompactGrid(panel,
200 2, 1,
201 6, 6,
202 6, 6);
203 setBottomComponent(panel);
204 }
205
206 public void resetTable() {
207 while (tcModel.getRowCount() > 0) {
208 tcModel.removeRow(0);
209 }
210 testCases.clear();
211 results.clear();
212 clearReasonTable();
213 }
214
215 protected void addTestCaseRow(TestCaseTag tct) {
216 String tcFileName = getScriptName(tct);
217 if ( ! testCases.containsKey(tcFileName) ) {
218 Object[] cols = new Object[8];
219 cols[TC_NUM] = new Integer(results.size() + 1);
220 cols[TEST_CASE] = tct.getName();
221 cols[STATUS] = runningImg;
222 cols[TC] = tct;
223 tcModel.addRow(cols);
224 Integer rowNum = new Integer(tcModel.getRowCount() - 1);
225 testCases.put(tcFileName, rowNum);
226 }
227 }
228
229 private String getScriptName(TestCaseTag tct) {
230 String scriptName = tct.getTestCase().getFile();
231 boolean notFound = true;
232 String tmpScriptName = null;
233 for (int i = 1; notFound; i++){
234 tmpScriptName = scriptName + i;
235 if (testCases.containsKey(tmpScriptName)){
236 Integer rowNum = (Integer)testCases.get(tmpScriptName);
237 ImageIcon statusImg = (ImageIcon)tcModel.getValueAt(rowNum.intValue(), STATUS);
238 if (statusImg == runningImg){
239 notFound = false;
240 }
241 }else{
242 notFound = false;
243 }
244 }
245 return tmpScriptName;
246 }
247
248 protected void reportTcResults(TestCaseTag tct) {
249 String tcFileName = getScriptName(tct);
250 int rowNum = ((Integer)testCases.get(tcFileName)).intValue();
251 TestCaseResult tcr = tct.getResults();
252 ImageIcon statusImg;
253
254 if (tcr.passed()) {
255 statusImg = passedImg;
256 } else {
257 statusImg = failedImg;
258 }
259 tcModel.setValueAt(statusImg, rowNum, STATUS);
260
261 String execTime = JameleonUtility.executionTimeToString(tcr.getExecutionTime());
262 tcModel.setValueAt(execTime, rowNum, EXEC_TIME);
263 int numRun = tcr.getCountableResults().size();
264 int numFailed = tcr.getFailedCountableResults().size();
265 tcModel.setValueAt(new Integer(numRun), rowNum, RUN);
266 tcModel.setValueAt(new Integer(numFailed), rowNum, FAIL);
267
268 String percentagePassed = "N/A";
269 try {
270 NumberFormat nf = NumberFormat.getPercentInstance();
271 int numPassed = numRun - numFailed;
272 if (numRun > 0) {
273 percentagePassed = nf.format((double) numPassed/numRun);
274 } else {
275 percentagePassed = nf.format(0);
276 }
277 } catch (ArithmeticException ae) {
278 System.err.println("Could not divide by 0 " + ae.getMessage());
279
280 }
281
282 tcModel.setValueAt(percentagePassed, rowNum, PASS);
283 results.add(tcr);
284 }
285
286 /***
287 * @param path The path to the image
288 * @param description The description of the image
289 * @return ImageIcon, or null if the path was invalid.
290 */
291 protected ImageIcon createImageIcon(String path, String description) {
292 URL imgURL = this.getClass().getResource(path);
293 ImageIcon icon = null;
294 if (imgURL != null) {
295 icon = new ImageIcon(imgURL, description);
296 } else {
297 System.err.println("Couldn't find file: " + path);
298 }
299 return icon;
300 }
301
302 public void clearReasonTable(){
303 while (tcReasonModel.getRowCount() > 0) {
304 tcReasonModel.setRowCount(0);
305 }
306 stackTrace.setText("");
307 }
308
309 private void checkForStop(TestCaseTag tct){
310 if (stopExecution) {
311 tct.setExecuteTestCase(false);
312 }
313 }
314
315
316
317
318 public void beginTestCase(TestCaseEvent event) {
319 TestCaseTag tct = (TestCaseTag)event.getSource();
320 checkForStop(tct);
321 addTestCaseRow(tct);
322 if (tcTable.getSelectedRow() == -1) {
323 clearReasonTable();
324 }
325 }
326
327 public void endTestCase(TestCaseEvent event) {
328 TestCaseTag tct = (TestCaseTag)event.getSource();
329 stepNextTag = false;
330 reportTcResults(tct);
331 }
332
333
334
335
336 public void beginFunction(FunctionEvent event, int rowNum) {
337 FunctionTag ft = (FunctionTag)event.getSource();
338 if (ft != null) {
339 highlightScriptLocation(ft);
340 checkForStop(ft.getTestCaseTag());
341 if (debug && (ft.isBreakPoint() || stepNextTag)) {
342 new FunctionDebugDialog(ft, rootFrame, this, ft.getElementName() +": " +ft.getFunctionId());
343 }
344 }
345 }
346
347 public void endFunction(FunctionEvent event, int rowNum) {
348 FunctionTag ft = (FunctionTag)event.getSource();
349 checkForStop(ft.getTestCaseTag());
350 FunctionResult fr = ft.getFunctionResults();
351 if (fr.failed() && tcTable.getSelectedRow() == -1) {
352 Object[] row = new Object[6];
353 row[TCResultsSelectionListeners.LINE] = new Integer(fr.getLineNumber());
354 if (fr.getErrorFile() != null) {
355 row[TCResultsSelectionListeners.URL] = snapShotImg;
356 }
357 row[TCResultsSelectionListeners.FUNCTION_ID] = fr.getIdentifier();
358 row[TCResultsSelectionListeners.ERR_MSG] = fr.getErrorMsg();
359 row[TCResultsSelectionListeners.OBJECT] = fr;
360 row[TCResultsSelectionListeners.ROW] = getFailedRowNum(fr);
361
362 tcReasonModel.addRow(row);
363 }
364 }
365
366
367
368
369 /***
370 * Gets called before the open method of a DataDrivable
371 * @param event - a DataDrivableEvent Object
372 */
373 public void openEvent(DataDrivableEvent event){
374
375 }
376
377 /***
378 * Gets called before the close method of a DataDrivable
379 * @param event - a DataDrivableEvent Object
380 */
381 public void closeEvent(DataDrivableEvent event){
382
383 }
384
385 /***
386 * Gets called before the executeDrivableRow
387 * @param event - a DataDrivableEvent Object
388 * @param rowNum - the current row number being executed from the data source.
389 */
390 public void executeRowEvent(DataDrivableEvent event, int rowNum){
391 DataDrivable dd = (DataDrivable)event.getSource();
392 if (dd instanceof LocationAwareTagSupport) {
393 highlightScriptLocation((LocationAwareTagSupport)dd);
394 }
395
396 if (debug && (stepNextTag || (dd instanceof BreakPoint && ((BreakPoint)dd).isBreakPoint()))) {
397 String title = "data drivable tag";
398 if (dd instanceof LocationAwareTagSupport) {
399 title = ((LocationAwareTagSupport)dd).getElementName();
400 }
401 new DataDrivableDebugDialog(event, rootFrame, this, title);
402 }
403 }
404
405 private void highlightScriptLocation(LocationAware la){
406 highlightScriptLocation(la, debug);
407 }
408
409 private void highlightScriptLocation(LocationAware la, boolean highlight){
410 if (highlight) {
411 int lineNum = la.getLineNumber()-1;
412 try{
413 if (sourceArea.getSelectionEnd() == 0) {
414 sourceArea.setCaretPosition(0);
415 }
416 sourceArea.setCaretPosition(sourceArea.getLineStartOffset(lineNum));
417 sourceArea.moveCaretPosition(sourceArea.getLineEndOffset(lineNum));
418 }catch(BadLocationException ble){
419 ble.printStackTrace();
420 }
421 }
422 }
423
424 protected Integer getFailedRowNum(JameleonTestResult result){
425 int rowNum = 0;
426 DataDrivableRowResult ddr = (DataDrivableRowResult)result.findAncestorByClass(DataDrivableRowResult.class);
427 if (ddr != null){
428 rowNum = ddr.getRowNum();
429 }
430 return new Integer(rowNum);
431 }
432
433
434
435
436
437 public class TCResultsSelectionListeners implements ListSelectionListener{
438 protected static final int ROW = 0;
439 protected static final int LINE = 1;
440 protected static final int URL = 2;
441 protected static final int FUNCTION_ID = 3;
442 protected static final int ERR_MSG = 4;
443 protected static final int OBJECT = 5;
444
445 /***
446 * Called whenever the value of the selection changes.
447 * @param e the event that characterizes the change.
448 */
449 public void valueChanged(ListSelectionEvent e) {
450 clearReasonTable();
451 int selectedRow = tcTable.getSelectedRow();
452 if (selectedRow > -1) {
453 TestCaseTag tct = (TestCaseTag)tcTable.getModel().getValueAt(selectedRow, TC);
454 TestCaseResult result = tct.getResults();
455 if (result.failed()) {
456 Object[] row = new Object[6];
457 List failedResults = result.getFailedResults();
458 Iterator it = failedResults.iterator();
459 JameleonTestResult tr;
460 while (it.hasNext()) {
461 tr = (JameleonTestResult)it.next();
462 row[LINE] = new Integer(tr.getLineNumber());
463 row[FUNCTION_ID] = tr.getIdentifier();
464 if (tr.getErrorFile() != null) {
465 row[URL] = snapShotImg;
466 }
467 row[ERR_MSG] = tr.getError().getMessage();
468 row[OBJECT] = tr;
469 row[ROW] = getFailedRowNum(tr);
470 tcReasonModel.addRow(row);
471 }
472 }
473 }
474
475 }
476
477 }
478
479 public class FTResultsSelectionListeners implements ListSelectionListener{
480 /***
481 * Called whenever the value of the selection changes.
482 * @param e the event that characterizes the change.
483 */
484 public void valueChanged(ListSelectionEvent e) {
485 int selectedRow = tcReasonTable.getSelectedRow();
486 if (selectedRow > -1) {
487 Object obj = tcReasonTable.getValueAt(selectedRow, TCResultsSelectionListeners.OBJECT);
488 if (obj instanceof JameleonTestResult) {
489 JameleonTestResult result = (JameleonTestResult) obj;
490 Throwable t = result.getError();
491 if (t != null) {
492 t = getCause(t);
493 stackTrace.setText(JameleonUtility.getStack(t));
494 stackTrace.setCaretPosition(0);
495 }
496 }
497 }
498 }
499
500 private Throwable getCause(Throwable t){
501 Throwable cause = t.getCause();
502 if (cause == null) {
503 cause = t;
504 }
505 return cause;
506 }
507
508 }
509
510 public class FTResultsMouseListener extends MouseAdapter{
511 public void mouseClicked(MouseEvent e) {
512 if (e.getClickCount() == 1) {
513 Point origin = e.getPoint();
514 int row = tcReasonTable.rowAtPoint(origin);
515 int col = tcReasonTable.columnAtPoint(origin);
516 if (row > -1 && col == TCResultsSelectionListeners.URL &&
517 tcReasonTable.getValueAt(row,TCResultsSelectionListeners.OBJECT) instanceof JameleonTestResult) {
518 JameleonTestResult tr = (JameleonTestResult)tcReasonTable.getValueAt(row,TCResultsSelectionListeners.OBJECT);
519 if (tr.getErrorFile() != null) {
520 try{
521 snapShotBrowser.goToUrl(tr.getErrorFile().toURI().toURL());
522 }catch (Exception ex){
523 ex.printStackTrace();
524 }
525 }
526 }else if (row > -1 && col == TCResultsSelectionListeners.LINE) {
527 JameleonTestResult tr = (JameleonTestResult)tcReasonTable.getValueAt(row, TCResultsSelectionListeners.OBJECT);
528 int selectedRow = tcTable.getSelectedRow();
529 if (selectedRow == -1) {
530 selectedRow = 0;
531 }
532 TestCaseTag tct = (TestCaseTag)tcTable.getValueAt(selectedRow, TC);
533 if (tct != null) {
534 try{
535 tcTree.setTestCaseSource(new File(new URI(tct.getFileName())), true);
536 highlightScriptLocation(tr, true);
537 }catch(Exception ex){
538 ex.printStackTrace();
539 }
540 }
541 }
542 }
543 }
544 }
545
546 public class TCResultsMouseListener extends MouseAdapter{
547 public void mouseClicked(MouseEvent e) {
548 if (e.getClickCount() == 1) {
549 Point origin = e.getPoint();
550 int row = tcTable.rowAtPoint(origin);
551 int col = tcTable.columnAtPoint(origin);
552 if (row > -1 && col == TestCaseResultsPane.STATUS &&
553 tcTable.getValueAt(row,TestCaseResultsPane.TC) instanceof TestCaseTag) {
554 TestCaseTag tct = (TestCaseTag)tcTable.getValueAt(row,TestCaseResultsPane.TC);
555 if (tct != null) {
556 try{
557 System.out.println(tct.getResultsFile());
558 snapShotBrowser.goToUrl(tct.getResultsFile().toURI().toURL());
559 }catch (Exception ex){
560 ex.printStackTrace();
561 }
562 }
563 }
564 }
565 }
566 }
567
568
569
570 }