KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > junit > ui > TestRunnerViewPart


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Julien Ruaux: jruaux@octo.com see bug 25324 Ability to know when tests are finished [junit]
11  * Vincent Massol: vmassol@octo.com 25324 Ability to know when tests are finished [junit]
12  * Sebastian Davids: sdavids@gmx.de 35762 JUnit View wasting a lot of screen space [JUnit]
13  *******************************************************************************/

14 package org.eclipse.jdt.internal.junit.ui;
15
16 import java.io.BufferedWriter JavaDoc;
17 import java.io.File JavaDoc;
18 import java.io.FileWriter JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.text.DateFormat JavaDoc;
21 import java.text.MessageFormat JavaDoc;
22 import java.text.NumberFormat JavaDoc;
23 import java.text.SimpleDateFormat JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27
28 import org.eclipse.core.commands.AbstractHandler;
29 import org.eclipse.core.commands.ExecutionEvent;
30 import org.eclipse.core.commands.ExecutionException;
31 import org.eclipse.core.commands.IHandler;
32
33 import org.eclipse.core.runtime.CoreException;
34 import org.eclipse.core.runtime.IProgressMonitor;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.core.runtime.Status;
37 import org.eclipse.core.runtime.jobs.ILock;
38 import org.eclipse.core.runtime.jobs.Job;
39
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.custom.CLabel;
42 import org.eclipse.swt.custom.SashForm;
43 import org.eclipse.swt.custom.ViewForm;
44 import org.eclipse.swt.dnd.Clipboard;
45 import org.eclipse.swt.events.ControlEvent;
46 import org.eclipse.swt.events.ControlListener;
47 import org.eclipse.swt.graphics.Image;
48 import org.eclipse.swt.graphics.Point;
49 import org.eclipse.swt.layout.GridData;
50 import org.eclipse.swt.layout.GridLayout;
51 import org.eclipse.swt.widgets.Composite;
52 import org.eclipse.swt.widgets.Display;
53 import org.eclipse.swt.widgets.FileDialog;
54 import org.eclipse.swt.widgets.Layout;
55 import org.eclipse.swt.widgets.Shell;
56 import org.eclipse.swt.widgets.ToolBar;
57
58 import org.eclipse.jface.action.Action;
59 import org.eclipse.jface.action.IAction;
60 import org.eclipse.jface.action.IMenuListener;
61 import org.eclipse.jface.action.IMenuManager;
62 import org.eclipse.jface.action.IStatusLineManager;
63 import org.eclipse.jface.action.IToolBarManager;
64 import org.eclipse.jface.action.MenuManager;
65 import org.eclipse.jface.action.Separator;
66 import org.eclipse.jface.dialogs.ErrorDialog;
67 import org.eclipse.jface.dialogs.MessageDialog;
68 import org.eclipse.jface.preference.IPreferenceStore;
69 import org.eclipse.jface.resource.ImageDescriptor;
70
71 import org.eclipse.ui.IActionBars;
72 import org.eclipse.ui.IEditorActionBarContributor;
73 import org.eclipse.ui.IEditorPart;
74 import org.eclipse.ui.IMemento;
75 import org.eclipse.ui.IPartListener2;
76 import org.eclipse.ui.IViewPart;
77 import org.eclipse.ui.IViewSite;
78 import org.eclipse.ui.IWorkbenchActionConstants;
79 import org.eclipse.ui.IWorkbenchPage;
80 import org.eclipse.ui.IWorkbenchPart;
81 import org.eclipse.ui.IWorkbenchPartReference;
82 import org.eclipse.ui.IWorkbenchWindow;
83 import org.eclipse.ui.PartInitException;
84 import org.eclipse.ui.PlatformUI;
85 import org.eclipse.ui.actions.ActionFactory;
86 import org.eclipse.ui.handlers.IHandlerActivation;
87 import org.eclipse.ui.handlers.IHandlerService;
88 import org.eclipse.ui.part.EditorActionBarContributor;
89 import org.eclipse.ui.part.ViewPart;
90 import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
91 import org.eclipse.ui.progress.UIJob;
92
93 import org.eclipse.debug.core.ILaunch;
94 import org.eclipse.debug.core.ILaunchConfiguration;
95 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
96
97 import org.eclipse.debug.ui.DebugUITools;
98
99 import org.eclipse.jdt.core.ElementChangedEvent;
100 import org.eclipse.jdt.core.IElementChangedListener;
101 import org.eclipse.jdt.core.IJavaElement;
102 import org.eclipse.jdt.core.IJavaElementDelta;
103 import org.eclipse.jdt.core.IJavaProject;
104 import org.eclipse.jdt.core.JavaCore;
105
106 import org.eclipse.jdt.internal.ui.viewsupport.ViewHistory;
107
108 import org.eclipse.jdt.junit.model.ITestElement.Result;
109
110 import org.eclipse.jdt.internal.junit.Messages;
111 import org.eclipse.jdt.internal.junit.launcher.ITestKind;
112 import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
113 import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry;
114 import org.eclipse.jdt.internal.junit.model.ITestRunSessionListener;
115 import org.eclipse.jdt.internal.junit.model.ITestSessionListener;
116 import org.eclipse.jdt.internal.junit.model.JUnitModel;
117 import org.eclipse.jdt.internal.junit.model.TestCaseElement;
118 import org.eclipse.jdt.internal.junit.model.TestElement;
119 import org.eclipse.jdt.internal.junit.model.TestRunSession;
120
121 /**
122  * A ViewPart that shows the results of a test run.
123  */

124 public class TestRunnerViewPart extends ViewPart {
125
126     public static final String JavaDoc NAME= "org.eclipse.jdt.junit.ResultView"; //$NON-NLS-1$
127

128     private static final String JavaDoc RERUN_LAST_COMMAND= "org.eclipse.jdt.junit.junitShortcut.rerunLast"; //$NON-NLS-1$
129
private static final String JavaDoc RERUN_FAILED_FIRST_COMMAND= "org.eclipse.jdt.junit.junitShortcut.rerunFailedFirst"; //$NON-NLS-1$
130

131     static final int REFRESH_INTERVAL= 200;
132     
133     static final int LAYOUT_FLAT= 0;
134     static final int LAYOUT_HIERARCHICAL= 1;
135     
136     /**
137      * Whether the output scrolls and reveals tests as they are executed.
138      */

139     protected boolean fAutoScroll = true;
140     /**
141      * The current orientation; either <code>VIEW_ORIENTATION_HORIZONTAL</code>
142      * <code>VIEW_ORIENTATION_VERTICAL</code>, or <code>VIEW_ORIENTATION_AUTOMATIC</code>.
143      */

144     private int fOrientation= VIEW_ORIENTATION_AUTOMATIC;
145     /**
146      * The current orientation; either <code>VIEW_ORIENTATION_HORIZONTAL</code>
147      * <code>VIEW_ORIENTATION_VERTICAL</code>.
148      */

149     private int fCurrentOrientation;
150     /**
151      * The current layout mode (LAYOUT_FLAT or LAYOUT_HIERARCHICAL).
152      */

153     private int fLayout= LAYOUT_HIERARCHICAL;
154     
155 // private boolean fTestIsRunning= false;
156

157     protected JUnitProgressBar fProgressBar;
158     protected ProgressImages fProgressImages;
159     protected Image fViewImage;
160     protected CounterPanel fCounterPanel;
161     protected boolean fShowOnErrorOnly= false;
162     protected Clipboard fClipboard;
163     protected volatile String JavaDoc fInfoMessage;
164
165     private FailureTrace fFailureTrace;
166     
167     private TestViewer fTestViewer;
168     /**
169      * Is the UI disposed?
170      */

171     private boolean fIsDisposed= false;
172     
173     /**
174      * Actions
175      */

176     private Action fNextAction;
177     private Action fPreviousAction;
178     
179     private StopAction fStopAction;
180     private JUnitCopyAction fCopyAction;
181     
182     private Action fRerunLastTestAction;
183     private IHandlerActivation fRerunLastActivation;
184     private Action fRerunFailedFirstAction;
185     private IHandlerActivation fRerunFailedFirstActivation;
186     
187     private Action fFailuresOnlyFilterAction;
188     private ScrollLockAction fScrollLockAction;
189     private ToggleOrientationAction[] fToggleOrientationActions;
190     private ShowTestHierarchyAction fShowTestHierarchyAction;
191     private ActivateOnErrorAction fActivateOnErrorAction;
192     private IMenuListener fViewMenuListener;
193
194     private TestRunSession fTestRunSession;
195     private TestSessionListener fTestSessionListener;
196     
197     private RunnerViewHistory fViewHistory;
198     private TestRunSessionListener fTestRunSessionListener;
199
200     final Image fStackViewIcon= TestRunnerViewPart.createImage("eview16/stackframe.gif");//$NON-NLS-1$
201
final Image fTestRunOKIcon= TestRunnerViewPart.createImage("eview16/junitsucc.gif"); //$NON-NLS-1$
202
final Image fTestRunFailIcon= TestRunnerViewPart.createImage("eview16/juniterr.gif"); //$NON-NLS-1$
203
final Image fTestRunOKDirtyIcon= TestRunnerViewPart.createImage("eview16/junitsuccq.gif"); //$NON-NLS-1$
204
final Image fTestRunFailDirtyIcon= TestRunnerViewPart.createImage("eview16/juniterrq.gif"); //$NON-NLS-1$
205

206     final Image fTestIcon= TestRunnerViewPart.createImage("obj16/test.gif"); //$NON-NLS-1$
207
final Image fTestOkIcon= TestRunnerViewPart.createImage("obj16/testok.gif"); //$NON-NLS-1$
208
final Image fTestErrorIcon= TestRunnerViewPart.createImage("obj16/testerr.gif"); //$NON-NLS-1$
209
final Image fTestFailIcon= TestRunnerViewPart.createImage("obj16/testfail.gif"); //$NON-NLS-1$
210
final Image fTestRunningIcon= TestRunnerViewPart.createImage("obj16/testrun.gif"); //$NON-NLS-1$
211
final Image fTestIgnoredIcon= TestRunnerViewPart.createImage("obj16/testignored.gif"); //$NON-NLS-1$
212

213     final ImageDescriptor fSuiteIconDescriptor= JUnitPlugin.getImageDescriptor("obj16/tsuite.gif"); //$NON-NLS-1$
214
final ImageDescriptor fSuiteOkIconDescriptor= JUnitPlugin.getImageDescriptor("obj16/tsuiteok.gif"); //$NON-NLS-1$
215
final ImageDescriptor fSuiteErrorIconDescriptor= JUnitPlugin.getImageDescriptor("obj16/tsuiteerror.gif"); //$NON-NLS-1$
216
final ImageDescriptor fSuiteFailIconDescriptor= JUnitPlugin.getImageDescriptor("obj16/tsuitefail.gif"); //$NON-NLS-1$
217
final ImageDescriptor fSuiteRunningIconDescriptor= JUnitPlugin.getImageDescriptor("obj16/tsuiterun.gif"); //$NON-NLS-1$
218

219     final Image fSuiteIcon= fSuiteIconDescriptor.createImage();
220     final Image fSuiteOkIcon= fSuiteOkIconDescriptor.createImage();
221     final Image fSuiteErrorIcon= fSuiteErrorIconDescriptor.createImage();
222     final Image fSuiteFailIcon= fSuiteFailIconDescriptor.createImage();
223     final Image fSuiteRunningIcon= fSuiteRunningIconDescriptor.createImage();
224     
225     // Persistence tags.
226
static final String JavaDoc TAG_PAGE= "page"; //$NON-NLS-1$
227
static final String JavaDoc TAG_RATIO= "ratio"; //$NON-NLS-1$
228
static final String JavaDoc TAG_TRACEFILTER= "tracefilter"; //$NON-NLS-1$
229
static final String JavaDoc TAG_ORIENTATION= "orientation"; //$NON-NLS-1$
230
static final String JavaDoc TAG_SCROLL= "scroll"; //$NON-NLS-1$
231
/**
232      * @since 3.2
233      */

234     static final String JavaDoc TAG_LAYOUT= "layout"; //$NON-NLS-1$
235
/**
236      * @since 3.2
237      */

238     static final String JavaDoc TAG_FAILURES_ONLY= "failuresOnly"; //$NON-NLS-1$
239

240     //orientations
241
static final int VIEW_ORIENTATION_VERTICAL= 0;
242     static final int VIEW_ORIENTATION_HORIZONTAL= 1;
243     static final int VIEW_ORIENTATION_AUTOMATIC= 2;
244     
245     private IMemento fMemento;
246
247     Image fOriginalViewImage;
248     IElementChangedListener fDirtyListener;
249     
250     
251 // private CTabFolder fTabFolder;
252
private SashForm fSashForm;
253     
254     private Composite fCounterComposite;
255     private Composite fParent;
256     
257     /**
258      * A Job that periodically updates view description, counters, and progress bar.
259      */

260     private UpdateUIJob fUpdateJob;
261     
262     /**
263      * A Job that runs as long as a test run is running.
264      * It is used to show busyness for running jobs in the view (title in italics).
265      */

266     private JUnitIsRunningJob fJUnitIsRunningJob;
267     private ILock fJUnitIsRunningLock;
268     public static final Object JavaDoc FAMILY_JUNIT_RUN = new Object JavaDoc();
269
270     private IPartListener2 fPartListener= new IPartListener2() {
271         public void partActivated(IWorkbenchPartReference ref) { }
272         public void partBroughtToTop(IWorkbenchPartReference ref) { }
273         public void partInputChanged(IWorkbenchPartReference ref) { }
274         public void partClosed(IWorkbenchPartReference ref) { }
275         public void partDeactivated(IWorkbenchPartReference ref) { }
276         public void partOpened(IWorkbenchPartReference ref) { }
277         
278         public void partVisible(IWorkbenchPartReference ref) {
279             if (getSite().getId().equals(ref.getId())) {
280                 fPartIsVisible= true;
281             }
282         }
283         
284         public void partHidden(IWorkbenchPartReference ref) {
285             if (getSite().getId().equals(ref.getId())) {
286                 fPartIsVisible= false;
287             }
288         }
289     };
290     
291     protected boolean fPartIsVisible= false;
292
293     
294     private class RunnerViewHistory extends ViewHistory {
295
296         public void configureHistoryListAction(IAction action) {
297             action.setText(JUnitMessages.TestRunnerViewPart_history);
298         }
299
300         public void configureHistoryDropDownAction(IAction action) {
301             action.setToolTipText(JUnitMessages.TestRunnerViewPart_test_run_history);
302             JUnitPlugin.setLocalImageDescriptors(action, "history_list.gif"); //$NON-NLS-1$
303
}
304         
305         public Action getClearAction() {
306             return new ClearAction();
307         }
308
309         public String JavaDoc getHistoryListDialogTitle() {
310             return JUnitMessages.TestRunnerViewPart_test_runs;
311         }
312
313         public String JavaDoc getHistoryListDialogMessage() {
314             return JUnitMessages.TestRunnerViewPart_select_test_run;
315         }
316
317         public Shell getShell() {
318             return fParent.getShell();
319         }
320
321         public List JavaDoc getHistoryEntries() {
322             return JUnitPlugin.getModel().getTestRunSessions();
323         }
324
325         public Object JavaDoc getCurrentEntry() {
326             return fTestRunSession;
327         }
328
329         public void setActiveEntry(Object JavaDoc entry) {
330             TestRunSession deactivatedSession= setActiveTestRunSession((TestRunSession) entry);
331             if (deactivatedSession != null)
332                 deactivatedSession.swapOut();
333         }
334
335         public void setHistoryEntries(List JavaDoc remainingEntries, Object JavaDoc activeEntry) {
336             setActiveTestRunSession((TestRunSession) activeEntry);
337             
338             List JavaDoc testRunSessions= JUnitPlugin.getModel().getTestRunSessions();
339             testRunSessions.removeAll(remainingEntries);
340             for (Iterator JavaDoc iter= testRunSessions.iterator(); iter.hasNext();) {
341                 JUnitPlugin.getModel().removeTestRunSession((TestRunSession) iter.next());
342             }
343             for (Iterator JavaDoc iter= remainingEntries.iterator(); iter.hasNext();) {
344                 TestRunSession remaining= (TestRunSession) iter.next();
345                 remaining.swapOut();
346             }
347         }
348
349         public ImageDescriptor getImageDescriptor(Object JavaDoc element) {
350             TestRunSession session= (TestRunSession) element;
351             if (session.isStopped())
352                 return fSuiteIconDescriptor;
353             
354             if (session.isRunning())
355                 return fSuiteRunningIconDescriptor;
356                 
357             Result result= session.getTestResult(true);
358             if (result == Result.OK)
359                 return fSuiteOkIconDescriptor;
360             else if (result == Result.ERROR)
361                 return fSuiteErrorIconDescriptor;
362             else if (result == Result.FAILURE)
363                 return fSuiteFailIconDescriptor;
364             else
365                 return fSuiteIconDescriptor;
366         }
367
368         public String JavaDoc getText(Object JavaDoc element) {
369             TestRunSession session= (TestRunSession) element;
370             if (session.getStartTime() == 0) {
371                 return session.getTestRunName();
372             } else {
373                 String JavaDoc startTime= DateFormat.getDateTimeInstance().format(new Date JavaDoc(session.getStartTime()));
374                 return Messages.format(JUnitMessages.TestRunnerViewPart_testName_startTime, new Object JavaDoc[] { session.getTestRunName(), startTime });
375             }
376         }
377         
378         public void addMenuEntries(MenuManager manager) {
379             manager.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new ImportTestRunSessionAction(fParent.getShell()));
380             if (fTestRunSession != null)
381                 manager.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, new ExportTestRunSessionAction(fParent.getShell(), fTestRunSession));
382         }
383
384         public String JavaDoc getMaxEntriesMessage() {
385             return JUnitMessages.TestRunnerViewPart_max_remembered;
386         }
387
388         public int getMaxEntries() {
389             IPreferenceStore store= JUnitPlugin.getDefault().getPreferenceStore();
390             return store.getInt(JUnitPreferencesConstants.MAX_TEST_RUNS);
391         }
392
393         public void setMaxEntries(int maxEntries) {
394             IPreferenceStore store= JUnitPlugin.getDefault().getPreferenceStore();
395             store.setValue(JUnitPreferencesConstants.MAX_TEST_RUNS, maxEntries);
396         }
397     }
398     
399     private static class ImportTestRunSessionAction extends Action {
400         private final Shell fShell;
401
402         public ImportTestRunSessionAction(Shell shell) {
403             super(JUnitMessages.TestRunnerViewPart_ImportTestRunSessionAction_name);
404             fShell= shell;
405         }
406         
407         public void run() {
408             FileDialog importDialog= new FileDialog(fShell, SWT.OPEN);
409             importDialog.setText(JUnitMessages.TestRunnerViewPart_ImportTestRunSessionAction_title);
410             importDialog.setFilterExtensions(new String JavaDoc[] {"*.xml", "*.*"}); //$NON-NLS-1$ //$NON-NLS-2$
411
String JavaDoc path= importDialog.open();
412             if (path == null)
413                 return;
414             
415             //TODO: MULTI: getFileNames()
416
File JavaDoc file= new File JavaDoc(path);
417             
418             try {
419                 JUnitModel.importTestRunSession(file);
420             } catch (CoreException e) {
421                 JUnitPlugin.log(e);
422                 ErrorDialog.openError(fShell, JUnitMessages.TestRunnerViewPart_ImportTestRunSessionAction_error_title, e.getStatus().getMessage(), e.getStatus());
423             }
424         }
425     }
426     
427     private static class ExportTestRunSessionAction extends Action {
428         private final TestRunSession fTestRunSession;
429         private final Shell fShell;
430
431         public ExportTestRunSessionAction(Shell shell, TestRunSession testRunSession) {
432             super(JUnitMessages.TestRunnerViewPart_ExportTestRunSessionAction_name);
433             fShell= shell;
434             fTestRunSession= testRunSession;
435         }
436         
437         public void run() {
438             FileDialog exportDialog= new FileDialog(fShell, SWT.SAVE);
439             exportDialog.setText(JUnitMessages.TestRunnerViewPart_ExportTestRunSessionAction_title);
440             exportDialog.setFileName(getFileName());
441             exportDialog.setFilterExtensions(new String JavaDoc[] {"*.xml", "*.*"}); //$NON-NLS-1$ //$NON-NLS-2$
442
String JavaDoc path= exportDialog.open();
443             if (path == null)
444                 return;
445             
446             //TODO: MULTI: getFileNames()
447
File JavaDoc file= new File JavaDoc(path);
448             
449             try {
450                 JUnitModel.exportTestRunSession(fTestRunSession, file);
451             } catch (CoreException e) {
452                 JUnitPlugin.log(e);
453                 ErrorDialog.openError(fShell, JUnitMessages.TestRunnerViewPart_ExportTestRunSessionAction_error_title, e.getStatus().getMessage(), e.getStatus());
454             }
455         }
456
457         private String JavaDoc getFileName() {
458             String JavaDoc testRunName= fTestRunSession.getTestRunName();
459             long startTime= fTestRunSession.getStartTime();
460             if (startTime == 0)
461                 return testRunName;
462             
463             String JavaDoc isoTime= new SimpleDateFormat JavaDoc("yyyyMMdd-HHmmss").format(new Date JavaDoc(startTime)); //$NON-NLS-1$
464
return testRunName + " " + isoTime + ".xml"; //$NON-NLS-1$ //$NON-NLS-2$
465
}
466     }
467
468     private class TestRunSessionListener implements ITestRunSessionListener {
469         public void sessionAdded(TestRunSession testRunSession) {
470             if (getSite().getWorkbenchWindow() == JUnitPlugin.getActiveWorkbenchWindow()) {
471                 TestRunSession deactivatedSession= setActiveTestRunSession(testRunSession);
472                 if (deactivatedSession != null)
473                     deactivatedSession.swapOut();
474                 String JavaDoc testRunName= fTestRunSession.getTestRunName();
475                 String JavaDoc msg;
476                 if (testRunSession.getLaunch() != null) {
477                     msg= Messages.format(JUnitMessages.TestRunnerViewPart_Launching, new Object JavaDoc[]{ testRunName });
478                 } else {
479                     msg= testRunName;
480                 }
481                 setContentDescription(msg);
482             }
483         }
484         public void sessionRemoved(TestRunSession testRunSession) {
485             if (testRunSession.equals(fTestRunSession)) {
486                 List JavaDoc testRunSessions= JUnitPlugin.getModel().getTestRunSessions();
487                 TestRunSession deactivatedSession;
488                 if (! testRunSessions.isEmpty()) {
489                     deactivatedSession= setActiveTestRunSession((TestRunSession) testRunSessions.get(0));
490                 } else {
491                     deactivatedSession= setActiveTestRunSession(null);
492                 }
493                 if (deactivatedSession != null)
494                     deactivatedSession.swapOut();
495             }
496         }
497     }
498     
499     private class TestSessionListener implements ITestSessionListener {
500         public void sessionStarted(){
501             fTestViewer.registerViewersRefresh();
502             fShowOnErrorOnly= getShowOnErrorOnly();
503             
504             startUpdateJobs();
505             
506             fStopAction.setEnabled(true);
507             fRerunLastTestAction.setEnabled(true);
508         }
509
510         public void sessionEnded(long elapsedTime){
511             fTestViewer.registerAutoScrollTarget(null);
512             
513             String JavaDoc[] keys= {elapsedTimeAsString(elapsedTime)};
514             String JavaDoc msg= Messages.format(JUnitMessages.TestRunnerViewPart_message_finish, keys);
515             registerInfoMessage(msg);
516                 
517             postSyncRunnable(new Runnable JavaDoc() {
518                 public void run() {
519                     if (isDisposed())
520                         return;
521                     fStopAction.setEnabled(lastLaunchIsKeptAlive());
522                     updateRerunFailedFirstAction();
523                     processChangesInUI();
524                     if (hasErrorsOrFailures()) {
525                         selectFirstFailure();
526                     }
527                     if (fDirtyListener == null) {
528                         fDirtyListener= new DirtyListener();
529                         JavaCore.addElementChangedListener(fDirtyListener);
530                     }
531                     warnOfContentChange();
532                 }
533             });
534             stopUpdateJobs();
535         }
536
537         public void sessionStopped(final long elapsedTime) {
538             fTestViewer.registerAutoScrollTarget(null);
539
540             registerInfoMessage(JUnitMessages.TestRunnerViewPart_message_stopped);
541             handleStopped();
542         }
543
544         public void sessionTerminated() {
545             fTestViewer.registerAutoScrollTarget(null);
546
547             registerInfoMessage(JUnitMessages.TestRunnerViewPart_message_terminated);
548             handleStopped();
549         }
550         
551         public void runningBegins() {
552             if (!fShowOnErrorOnly)
553                 postShowTestResultsView();
554         }
555
556         public void testStarted(TestCaseElement testCaseElement) {
557             fTestViewer.registerAutoScrollTarget(testCaseElement);
558             fTestViewer.registerViewerUpdate(testCaseElement);
559
560             String JavaDoc className= testCaseElement.getClassName();
561             String JavaDoc method= testCaseElement.getTestMethodName();
562             String JavaDoc status= Messages.format(JUnitMessages.TestRunnerViewPart_message_started, new String JavaDoc[] { className, method });
563             registerInfoMessage(status);
564         }
565
566         public void testFailed(TestElement testElement, TestElement.Status status, String JavaDoc trace, String JavaDoc expected, String JavaDoc actual) {
567             if (isAutoScroll()) {
568                 fTestViewer.registerFailedForAutoScroll(testElement);
569             }
570             fTestViewer.registerViewerUpdate(testElement);
571
572             // show the view on the first error only
573
if (fShowOnErrorOnly && (getErrorsPlusFailures() == 1))
574                 postShowTestResultsView();
575             
576             //TODO:
577
// [Bug 35590] JUnit window doesn't report errors from junit.extensions.TestSetup [JUnit]
578
// when a failure occurs in test setup then no test is running
579
// to update the views we artificially signal the end of a test run
580
// if (!fTestIsRunning) {
581
// fTestIsRunning= false;
582
// testEnded(testCaseElement);
583
// }
584
}
585         
586         public void testEnded(TestCaseElement testCaseElement){
587             fTestViewer.registerViewerUpdate(testCaseElement);
588         }
589
590         public void testReran(TestCaseElement testCaseElement, TestElement.Status status, String JavaDoc trace, String JavaDoc expectedResult, String JavaDoc actualResult) {
591             fTestViewer.registerViewerUpdate(testCaseElement); //TODO: autoExpand?
592
postSyncProcessChanges();
593             showFailure(testCaseElement);
594         }
595         
596         public void testAdded(TestElement testElement) {
597             fTestViewer.registerTestAdded(testElement);
598         }
599         
600         public boolean acceptsSwapToDisk() {
601             return false;
602         }
603     }
604     
605     private class UpdateUIJob extends UIJob {
606         private boolean fRunning= true;
607         
608         public UpdateUIJob(String JavaDoc name) {
609             super(name);
610             setSystem(true);
611         }
612         public IStatus runInUIThread(IProgressMonitor monitor) {
613             if (!isDisposed()) {
614                 processChangesInUI();
615             }
616             schedule(REFRESH_INTERVAL);
617             return Status.OK_STATUS;
618         }
619         
620         public void stop() {
621             fRunning= false;
622         }
623         public boolean shouldSchedule() {
624             return fRunning;
625         }
626     }
627
628     private class JUnitIsRunningJob extends Job {
629         public JUnitIsRunningJob(String JavaDoc name) {
630             super(name);
631             setSystem(true);
632         }
633         public IStatus run(IProgressMonitor monitor) {
634             // wait until the test run terminates
635
fJUnitIsRunningLock.acquire();
636             return Status.OK_STATUS;
637         }
638         public boolean belongsTo(Object JavaDoc family) {
639             return family == TestRunnerViewPart.FAMILY_JUNIT_RUN;
640         }
641     }
642
643     private class ClearAction extends Action {
644         public ClearAction() {
645             setText(JUnitMessages.TestRunnerViewPart_clear_history_label);
646             
647             boolean enabled= false;
648             List JavaDoc testRunSessions= JUnitPlugin.getModel().getTestRunSessions();
649             for (Iterator JavaDoc iter= testRunSessions.iterator(); iter.hasNext();) {
650                 TestRunSession testRunSession= (TestRunSession) iter.next();
651                 if (! testRunSession.isRunning()) {
652                     enabled= true;
653                     break;
654                 }
655             }
656             setEnabled(enabled);
657         }
658         
659         public void run() {
660             List JavaDoc testRunSessions= getRunningSessions();
661             Object JavaDoc first= testRunSessions.isEmpty() ? null : testRunSessions.get(0);
662             fViewHistory.setHistoryEntries(testRunSessions, first);
663         }
664
665         private List JavaDoc getRunningSessions() {
666             List JavaDoc testRunSessions= JUnitPlugin.getModel().getTestRunSessions();
667             for (Iterator JavaDoc iter= testRunSessions.iterator(); iter.hasNext();) {
668                 TestRunSession testRunSession= (TestRunSession) iter.next();
669                 if (! testRunSession.isRunning()) {
670                     iter.remove();
671                 }
672             }
673             return testRunSessions;
674         }
675     }
676
677     private class StopAction extends Action {
678         public StopAction() {
679             setText(JUnitMessages.TestRunnerViewPart_stopaction_text);
680             setToolTipText(JUnitMessages.TestRunnerViewPart_stopaction_tooltip);
681             JUnitPlugin.setLocalImageDescriptors(this, "stop.gif"); //$NON-NLS-1$
682
}
683
684         public void run() {
685             stopTest();
686             setEnabled(fal