Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 560   Methods: 42
NCLOC: 351   Classes: 4
 
 Source file Conditionals Statements Methods TOTAL
JUnitPanel.java 10.7% 40.1% 38.1% 34.5%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava.ui;
 38   
 39    import edu.rice.cs.drjava.model.SingleDisplayModel;
 40    import edu.rice.cs.drjava.model.DJError;
 41    import edu.rice.cs.drjava.model.junit.JUnitError;
 42    import edu.rice.cs.drjava.model.junit.JUnitErrorModel;
 43    import edu.rice.cs.util.UnexpectedException;
 44    import edu.rice.cs.util.swing.BorderlessScrollPane;
 45    import edu.rice.cs.util.swing.RightClickMouseAdapter;
 46   
 47    import javax.swing.*;
 48    import javax.swing.border.EmptyBorder;
 49    import javax.swing.text.*;
 50    import java.awt.*;
 51    import java.awt.event.ActionEvent;
 52    import java.awt.event.ActionListener;
 53    import java.awt.event.MouseEvent;
 54    import java.io.File;
 55    import java.util.HashMap;
 56   
 57    /** The panel that displays all the testing errors.
 58    * @version $Id: JUnitPanel.java 5439 2011-08-11 17:13:04Z rcartwright $
 59    */
 60    public class JUnitPanel extends ErrorPanel {
 61    private static final String START_JUNIT_MSG = "Testing in progress. Please wait ...\n";
 62    private static final String JUNIT_FINISHED_MSG = "All tests completed successfully.\n";
 63    private static final String NO_TESTS_MSG = "";
 64   
 65    private static final SimpleAttributeSet OUT_OF_SYNC_ATTRIBUTES = _getOutOfSyncAttributes();
 66  6 private static final SimpleAttributeSet _getOutOfSyncAttributes() {
 67  6 SimpleAttributeSet s = new SimpleAttributeSet();
 68  6 s.addAttribute(StyleConstants.Foreground, Color.red.darker());
 69  6 s.addAttribute(StyleConstants.Bold, Boolean.TRUE);
 70  6 return s;
 71    }
 72   
 73    private static final SimpleAttributeSet TEST_PASS_ATTRIBUTES = _getTestPassAttributes();
 74  6 private static final SimpleAttributeSet _getTestPassAttributes() {
 75  6 SimpleAttributeSet s = new SimpleAttributeSet();
 76  6 s.addAttribute(StyleConstants.Foreground, Color.green.darker());
 77  6 return s;
 78    }
 79   
 80    private static final SimpleAttributeSet TEST_FAIL_ATTRIBUTES = _getTestFailAttributes();
 81  6 private static final SimpleAttributeSet _getTestFailAttributes() {
 82  6 SimpleAttributeSet s = new SimpleAttributeSet();
 83  6 s.addAttribute(StyleConstants.Foreground, Color.red);
 84  6 return s;
 85    }
 86   
 87    private static final String TEST_OUT_OF_SYNC =
 88    "The documents being tested have been modified and should be recompiled!\n";
 89   
 90    protected JUnitErrorListPane _errorListPane;
 91    private final MainFrame _mainFrame; // only used in assert statements
 92    private int _testCount;
 93    private boolean _testsSuccessful;
 94   
 95    private volatile JUnitProgressBar _progressBar;
 96   
 97    private Action _showStackTraceAction = new AbstractAction("Show Stack Trace") {
 98  0 public void actionPerformed(ActionEvent ae) {
 99  0 if (_error != null) {
 100  0 _displayStackTrace(_error);
 101    }
 102    }
 103    };
 104   
 105    private volatile JButton _showStackTraceButton;
 106   
 107    /** The currently selected error. */
 108    private volatile JUnitError _error = null;
 109    private volatile Window _stackFrame = null;
 110    private volatile JTextArea _stackTextArea;
 111    private final JLabel _errorLabel = new JLabel();
 112    private final JLabel _testLabel = new JLabel();
 113    private final JLabel _fileLabel = new JLabel();
 114   
 115    /** Constructor.
 116    * @param model SingleDisplayModel in which we are running
 117    * @param frame MainFrame in which we are displayed
 118    */
 119  38 public JUnitPanel(SingleDisplayModel model, MainFrame frame) {
 120  38 super(model, frame, "Test Output", "Test Progress");
 121  38 _mainFrame = frame;
 122  38 _testCount = 0;
 123  38 _testsSuccessful = true;
 124   
 125  38 _progressBar = new JUnitProgressBar();
 126  38 _progressBar.setUI(new javax.swing.plaf.basic.BasicProgressBarUI());
 127  38 _showStackTraceButton = new JButton(_showStackTraceAction);
 128  38 customPanel.add(_progressBar, BorderLayout.NORTH);
 129  38 customPanel.add(_showStackTraceButton, BorderLayout.SOUTH);
 130   
 131  38 _errorListPane = new JUnitErrorListPane();
 132  38 setErrorListPane(_errorListPane);
 133    }
 134   
 135    /** Returns the JUnitErrorListPane that this panel manages. */
 136  76 public JUnitErrorListPane getErrorListPane() { return _errorListPane; }
 137   
 138  0 protected JUnitErrorModel getErrorModel() { return getModel().getJUnitModel().getJUnitErrorModel(); }
 139   
 140    /** Updates all document styles with the attributes contained in newSet.
 141    * @param newSet Style containing new attributes to use.
 142    */
 143  38 protected void _updateStyles(AttributeSet newSet) {
 144  38 super._updateStyles(newSet);
 145  38 OUT_OF_SYNC_ATTRIBUTES.addAttributes(newSet);
 146  38 StyleConstants.setBold(OUT_OF_SYNC_ATTRIBUTES, true); // should always be bold
 147  38 TEST_PASS_ATTRIBUTES.addAttributes(newSet);
 148  38 TEST_FAIL_ATTRIBUTES.addAttributes(newSet);
 149    }
 150   
 151    /** called when work begins */
 152  0 public void setJUnitInProgress() {
 153  0 _errorListPane.setJUnitInProgress();
 154    }
 155   
 156    /** Closes this panel and resets the corresponding model. */
 157  4 @Override
 158    protected void _close() {
 159  4 super._close();
 160  4 getModel().getJUnitModel().resetJUnitErrors();
 161  4 reset();
 162    }
 163   
 164    /** Reset the errors to the current error information. */
 165  42 public void reset() {
 166  42 JUnitErrorModel juem = getModel().getJUnitModel().getJUnitErrorModel();
 167  42 boolean testsHaveRun = false;
 168  42 if (juem != null) {
 169  42 _numErrors = juem.getNumErrors();
 170  42 testsHaveRun = juem.haveTestsRun();
 171    }
 172  0 else _numErrors = 0;
 173  42 _errorListPane.updateListPane(testsHaveRun); //changed!!
 174  42 repaint();
 175    }
 176   
 177    /** Resets the progress bar to start counting the given number of tests. */
 178  0 public void progressReset(int numTests) {
 179  0 _progressBar.reset();
 180  0 _progressBar.start(numTests);
 181  0 _testsSuccessful = true;
 182  0 _testCount = 0;
 183    }
 184   
 185    /** Steps the progress bar forward by one test.
 186    * @param successful Whether the last test was successful or not.
 187    */
 188  0 public void progressStep(boolean successful) {
 189  0 _testCount++;
 190  0 _testsSuccessful &= successful;
 191  0 _progressBar.step(_testCount, _testsSuccessful);
 192    }
 193   
 194  0 public void testStarted(String className, String testName) { }
 195   
 196  0 private void _displayStackTrace (JUnitError e) {
 197  0 _errorLabel.setText((e.isWarning() ? "Error: " : "Failure: ") +
 198    e.message());
 199  0 _fileLabel.setText("File: " + (new File(e.fileName())).getName());
 200  0 if (!e.testName().equals("")) {
 201  0 _testLabel.setText("Test: " + e.testName());
 202    }
 203    else {
 204  0 _testLabel.setText("");
 205    }
 206  0 _stackTextArea.setText(e.toString());
 207  0 _stackTextArea.setCaretPosition(0);
 208  0 _frame.setPopupLoc(_stackFrame);
 209  0 _stackFrame.setVisible(true);
 210    }
 211   
 212    /** A pane to show JUnit errors. It acts like a listbox (clicking selects an item) but items can each wrap, etc. */
 213    public class JUnitErrorListPane extends ErrorPanel.ErrorListPane {
 214    private JPopupMenu _popMenu;
 215    private String _runningTestName;
 216    private boolean _warnedOutOfSync;
 217    private static final String JUNIT_WARNING = "junit.framework.TestSuite$1.warning";
 218   
 219    /** Maps any test names in the currently running suite to the position that they appear in the list pane. */
 220    private final HashMap<String, Position> _runningTestNamePositions;
 221   
 222    /** Constructs the JUnitErrorListPane. */
 223  38 public JUnitErrorListPane() {
 224  38 removeMouseListener(defaultMouseListener);
 225  38 _popMenu = new JPopupMenu();
 226  38 _popMenu.add(_showStackTraceAction);
 227  38 _error = null;
 228  38 _setupStackTraceFrame();
 229  38 addMouseListener(new PopupAdapter());
 230  38 _runningTestName = null;
 231  38 _runningTestNamePositions = new HashMap<String, Position>();
 232  38 _showStackTraceButton.setEnabled(false);
 233    }
 234   
 235  0 private String _getTestFromName(String name) {
 236  0 int paren = name.indexOf('(');
 237   
 238  0 if (paren > 0) return name.substring(0, paren);
 239   
 240  0 else throw new IllegalArgumentException("Name does not contain any parens: " + name);
 241    }
 242   
 243  0 private String _getClassFromName(String name) {
 244  0 int paren = name.indexOf('(');
 245   
 246  0 if ((paren > -1) && (paren < name.length())) return name.substring(paren + 1, name.length() - 1);
 247  0 else throw new IllegalArgumentException("Name does not contain any parens: " + name);
 248    }
 249   
 250    /** Provides the ability to display the name of the test being run. */
 251  0 public void testStarted(String name) {
 252  0 if (name.indexOf('(') < 0) return;
 253   
 254  0 String testName = _getTestFromName(name);
 255  0 String className = _getClassFromName(name);
 256  0 String fullName = className + "." + testName;
 257  0 if (fullName.equals(JUNIT_WARNING)) return;
 258  0 ErrorDocument doc = getErrorDocument();
 259  0 try {
 260  0 int len = doc.getLength();
 261    // Insert the classname if it has changed
 262  0 if (! className.equals(_runningTestName)) {
 263  0 _runningTestName = className;
 264  0 doc.insertString(len, " " + className + "\n", NORMAL_ATTRIBUTES);
 265  0 len = doc.getLength();
 266    }
 267   
 268    // Insert the test name, remembering its position
 269  0 doc.insertString(len, " ", NORMAL_ATTRIBUTES);
 270  0 len = doc.getLength();
 271  0 doc.insertString(len, testName + "\n", NORMAL_ATTRIBUTES);
 272  0 Position pos = doc.createPosition(len);
 273  0 _runningTestNamePositions.put(fullName, pos);
 274  0 setCaretPosition(len);
 275    }
 276    catch (BadLocationException ble) {
 277    // Inserting at end, shouldn't happen
 278  0 throw new UnexpectedException(ble);
 279    }
 280    }
 281   
 282    /** Displays the results of a test that has finished. */
 283  0 public void testEnded(String name, boolean wasSuccessful, boolean causedError) {
 284  0 if (name.indexOf('(')<0) return;
 285   
 286  0 String testName = _getTestFromName(name);
 287  0 String fullName = _getClassFromName(name) + "." + testName;
 288  0 if (fullName.equals(JUNIT_WARNING)) return;
 289   
 290  0 ErrorDocument doc = getErrorDocument();
 291  0 Position namePos = _runningTestNamePositions.get(fullName);
 292  0 AttributeSet set;
 293  0 if (! wasSuccessful || causedError) set = TEST_FAIL_ATTRIBUTES;
 294  0 else set = TEST_PASS_ATTRIBUTES;
 295  0 if (namePos != null) {
 296  0 int index = namePos.getOffset();
 297  0 int length = testName.length();
 298  0 doc.setCharacterAttributes(index, length, set, false);
 299    }
 300    }
 301   
 302    /** Puts the error pane into "junit in progress" state. Only runs in event thread. */
 303  0 public void setJUnitInProgress() {
 304  0 assert EventQueue.isDispatchThread();
 305  0 _errorListPositions = new Position[0];
 306  0 progressReset(0);
 307  0 _runningTestNamePositions.clear();
 308  0 _runningTestName = null;
 309  0 _warnedOutOfSync = false;
 310   
 311  0 ErrorDocument doc = new ErrorDocument(getErrorDocumentTitle());
 312    // _checkSync(doc);
 313   
 314  0 doc.append(START_JUNIT_MSG, BOLD_ATTRIBUTES);
 315  0 setDocument(doc);
 316  0 selectNothing();
 317    }
 318   
 319    /** Used to show that testing was unsuccessful. */
 320  0 protected void _updateWithErrors() throws BadLocationException {
 321    //DefaultStyledDocument doc = new DefaultStyledDocument();
 322  0 ErrorDocument doc = getErrorDocument();
 323    // _checkSync(doc);
 324  0 _updateWithErrors("test", "failed", doc);
 325    }
 326   
 327    /** Gets the message indicating the number of errors and warnings.*/
 328  0 protected String _getNumErrorsMessage(String failureName, String failureMeaning) {
 329  0 StringBuilder numErrMsg;
 330   
 331    /** Used for display purposes only */
 332  0 int numCompErrs = getErrorModel().getNumCompErrors();
 333  0 int numWarnings = getErrorModel().getNumWarnings();
 334   
 335  0 if (! getErrorModel().hasOnlyWarnings()) {
 336  0 numErrMsg = new StringBuilder(numCompErrs + " " + failureName); //failureName = error or test (for compilation and JUnit testing respectively)
 337  0 if (numCompErrs > 1) numErrMsg.append("s");
 338  0 numErrMsg.append(" " + failureMeaning);
 339  0 if (numWarnings > 0) numErrMsg.append(" and " + numWarnings + " warning");
 340    }
 341  0 else numErrMsg = new StringBuilder(numWarnings + " warning");
 342   
 343  0 if (numWarnings > 1) numErrMsg.append("s");
 344  0 if (numWarnings > 0) numErrMsg.append(" found");
 345   
 346  0 numErrMsg.append(":\n");
 347   
 348  0 return numErrMsg.toString();
 349    }
 350   
 351  0 protected void _updateWithErrors(String failureName, String failureMeaning, ErrorDocument doc)
 352    throws BadLocationException {
 353    // Print how many errors
 354  0 _replaceInProgressText(_getNumErrorsMessage(failureName, failureMeaning));
 355   
 356  0 _insertErrors(doc);
 357   
 358    // Select the first error
 359  0 switchToError(0);
 360    }
 361   
 362    /** Replaces the "Testing in progress..." text with the given message. Only runs in event thread.
 363    * @param msg the text to insert
 364    */
 365  42 public void _replaceInProgressText(String msg) throws BadLocationException {
 366  42 assert ! _mainFrame.isVisible() || EventQueue.isDispatchThread();
 367  42 int start = 0;
 368  0 if (_warnedOutOfSync) { start = TEST_OUT_OF_SYNC.length(); }
 369  42 int len = START_JUNIT_MSG.length();
 370  42 ErrorDocument doc = getErrorDocument();
 371  42 if (doc.getLength() >= len + start) {
 372  0 doc.remove(start, len);
 373  0 doc.insertString(start, msg, BOLD_ATTRIBUTES);
 374    }
 375    }
 376   
 377    /** Returns the string to identify a warning. In JUnit, warnings (the odd case) indicate errors/exceptions.
 378    */
 379  0 protected String _getWarningText() { return "Error: "; }
 380   
 381    /** Returns the string to identify an error. In JUnit, errors (the normal case) indicate TestFailures. */
 382  0 protected String _getErrorText() { return "Failure: "; }
 383   
 384    /** Updates the list pane with no errors. */
 385  42 protected void _updateNoErrors(boolean haveTestsRun) throws BadLocationException {
 386    //DefaultStyledDocument doc = new DefaultStyledDocument();
 387    // _checkSync(getDocument());
 388  42 _replaceInProgressText(haveTestsRun ? JUNIT_FINISHED_MSG : NO_TESTS_MSG);
 389   
 390  42 selectNothing();
 391  42 setCaretPosition(0);
 392    }
 393   
 394    // /** Checks the document being tested to see if it's in sync. If not,
 395    // * displays a message in the document in the test output pane.
 396    // */
 397    // private void _checkSync(Document doc) {
 398    // if (_warnedOutOfSync) return;
 399    // List<OpenDefinitionsDocument> odds = _odds; // grab current _odds
 400    // for (OpenDefinitionsDocument odoc: odds) {
 401    // if (! odoc.checkIfClassFileInSync()) {
 402    // try {
 403    // doc.insertString(0, TEST_OUT_OF_SYNC, OUT_OF_SYNC_ATTRIBUTES);
 404    // _warnedOutOfSync = true;
 405    // return;
 406    // }
 407    // catch (BadLocationException ble) {
 408    // throw new UnexpectedException(ble);
 409    // }
 410    // }
 411    // }
 412    // }
 413   
 414  38 private void _setupStackTraceFrame() {
 415    //DrJava.consoleOut().println("Stack Trace for Error: \n" + e.stackTrace());
 416  38 JDialog _dialog = new JDialog(_frame,"JUnit Error Stack Trace",false);
 417  38 _stackFrame = _dialog;
 418  38 _stackTextArea = new JTextArea();
 419  38 _stackTextArea.setEditable(false);
 420  38 _stackTextArea.setLineWrap(false);
 421  38 JScrollPane scroll = new BorderlessScrollPane(_stackTextArea,
 422    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 423    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
 424   
 425  38 ActionListener closeListener = new ActionListener() {
 426  0 public void actionPerformed(ActionEvent e) {
 427  0 _stackFrame.setVisible(false);
 428    }
 429    };
 430  38 JButton closeButton = new JButton("Close");
 431  38 closeButton.addActionListener(closeListener);
 432  38 JPanel closePanel = new JPanel(new BorderLayout());
 433  38 closePanel.setBorder(new EmptyBorder(5,5,0,0));
 434  38 closePanel.add(closeButton, BorderLayout.EAST);
 435  38 JPanel cp = new JPanel(new BorderLayout());
 436  38 _dialog.setContentPane(cp);
 437  38 cp.setBorder(new EmptyBorder(5,5,5,5));
 438  38 cp.add(scroll, BorderLayout.CENTER);
 439  38 cp.add(closePanel, BorderLayout.SOUTH);
 440  38 JPanel topPanel = new JPanel(new GridLayout(0,1,0,5));
 441  38 topPanel.setBorder(new EmptyBorder(0,0,5,0));
 442  38 topPanel.add(_fileLabel);
 443  38 topPanel.add(_testLabel);
 444  38 topPanel.add(_errorLabel);
 445  38 cp.add(topPanel, BorderLayout.NORTH);
 446  38 _dialog.setSize(600, 500);
 447    // initial location is relative to parent (MainFrame)
 448    }
 449   
 450    /** Overrides selectItem in ErrorListPane to update the current _error selected
 451    * and enabling the _showStackTraceButton.
 452    */
 453  0 public void selectItem(DJError error) {
 454  0 super.selectItem(error);
 455  0 _error = (JUnitError) error;
 456  0 _showStackTraceButton.setEnabled(true);
 457    }
 458   
 459   
 460    /** Overrides _removeListHighlight in ErrorListPane to disable the _showStackTraceButton. */
 461  42 protected void _removeListHighlight() {
 462  42 super._removeListHighlight();
 463  42 _showStackTraceButton.setEnabled(false);
 464    }
 465   
 466    // /** Updates the UI to a new look and feel. Need to update the contained popup menu as well.
 467    // * Currently, we don't support changing the look and feel on the fly, so this is disabled.
 468    // */
 469    // public void updateUI() {
 470    // super.updateUI();
 471    // if (_popMenu != null) {
 472    // SwingUtilities.updateComponentTreeUI(_popMenu);
 473    // }
 474    // }
 475   
 476    private class PopupAdapter extends RightClickMouseAdapter {
 477    /** Show popup if the click is on an error.
 478    * @param e the MouseEvent correponding to this click
 479    */
 480  0 public void mousePressed(MouseEvent e) {
 481  0 if (_selectError(e)) {
 482  0 super.mousePressed(e);
 483    }
 484    }
 485   
 486    /** Show popup if the click is on an error.
 487    * @param e the MouseEvent correponding to this click
 488    */
 489  0 public void mouseReleased(MouseEvent e) {
 490  0 if (_selectError(e)) super.mouseReleased(e);
 491    }
 492   
 493    /** Select the error at the given mouse event.
 494    * @param e the MouseEvent correponding to this click
 495    * @return true iff the mouse click is over an error
 496    */
 497  0 private boolean _selectError(MouseEvent e) {
 498    //TODO: get rid of cast in the next line, if possible
 499  0 _error = (JUnitError)_errorAtPoint(e.getPoint());
 500   
 501  0 if (_isEmptySelection() && _error != null) {
 502  0 _errorListPane.switchToError(_error);
 503  0 return true;
 504    }
 505    else {
 506  0 selectNothing();
 507  0 return false;
 508    }
 509    }
 510   
 511    /** Shows the popup menu for this mouse adapter.
 512    * @param e the MouseEvent correponding to this click
 513    */
 514  0 protected void _popupAction(MouseEvent e) { _popMenu.show(e.getComponent(), e.getX(), e.getY()); }
 515    }
 516  38 public String getErrorDocumentTitle() { return "Javadoc Errors"; }
 517    }
 518   
 519   
 520    /** A progress bar showing the status of JUnit tests.
 521    * Green until a test fails, then red.
 522    * Adapted from JUnit code.
 523    */
 524    static class JUnitProgressBar extends JProgressBar {
 525    private boolean _hasError = false;
 526   
 527  38 public JUnitProgressBar() {
 528  38 super();
 529  38 setForeground(getStatusColor());
 530    }
 531   
 532  38 private Color getStatusColor() {
 533  38 if (_hasError) {
 534  0 return Color.red;
 535    }
 536    else {
 537  38 return Color.green;
 538    }
 539    }
 540   
 541  0 public void reset() {
 542  0 _hasError = false;
 543  0 setForeground(getStatusColor());
 544  0 setValue(0);
 545    }
 546   
 547  0 public void start(int total) {
 548  0 setMaximum(total);
 549  0 reset();
 550    }
 551   
 552  0 public void step(int value, boolean successful) {
 553  0 setValue(value);
 554  0 if (!_hasError && !successful) {
 555  0 _hasError= true;
 556  0 setForeground(getStatusColor());
 557    }
 558    }
 559    }
 560    }