001    package junit.framework;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.Enumeration;
006    import java.util.List;
007    
008    /**
009     * A <code>TestResult</code> collects the results of executing
010     * a test case. It is an instance of the Collecting Parameter pattern.
011     * The test framework distinguishes between <i>failures</i> and <i>errors</i>.
012     * A failure is anticipated and checked for with assertions. Errors are
013     * unanticipated problems like an {@link ArrayIndexOutOfBoundsException}.
014     *
015     * @see Test
016     */
017    public class TestResult {
018        protected List<TestFailure> fFailures;
019        protected List<TestFailure> fErrors;
020        protected List<TestListener> fListeners;
021        protected int fRunTests;
022        private boolean fStop;
023    
024        public TestResult() {
025            fFailures = new ArrayList<TestFailure>();
026            fErrors = new ArrayList<TestFailure>();
027            fListeners = new ArrayList<TestListener>();
028            fRunTests = 0;
029            fStop = false;
030        }
031    
032        /**
033         * Adds an error to the list of errors. The passed in exception
034         * caused the error.
035         */
036        public synchronized void addError(Test test, Throwable e) {
037            fErrors.add(new TestFailure(test, e));
038            for (TestListener each : cloneListeners()) {
039                each.addError(test, e);
040            }
041        }
042    
043        /**
044         * Adds a failure to the list of failures. The passed in exception
045         * caused the failure.
046         */
047        public synchronized void addFailure(Test test, AssertionFailedError e) {
048            fFailures.add(new TestFailure(test, e));
049            for (TestListener each : cloneListeners()) {
050                each.addFailure(test, e);
051            }
052        }
053    
054        /**
055         * Registers a TestListener.
056         */
057        public synchronized void addListener(TestListener listener) {
058            fListeners.add(listener);
059        }
060    
061        /**
062         * Unregisters a TestListener.
063         */
064        public synchronized void removeListener(TestListener listener) {
065            fListeners.remove(listener);
066        }
067    
068        /**
069         * Returns a copy of the listeners.
070         */
071        private synchronized List<TestListener> cloneListeners() {
072            List<TestListener> result = new ArrayList<TestListener>();
073            result.addAll(fListeners);
074            return result;
075        }
076    
077        /**
078         * Informs the result that a test was completed.
079         */
080        public void endTest(Test test) {
081            for (TestListener each : cloneListeners()) {
082                each.endTest(test);
083            }
084        }
085    
086        /**
087         * Gets the number of detected errors.
088         */
089        public synchronized int errorCount() {
090            return fErrors.size();
091        }
092    
093        /**
094         * Returns an Enumeration for the errors.
095         */
096        public synchronized Enumeration<TestFailure> errors() {
097            return Collections.enumeration(fErrors);
098        }
099    
100    
101        /**
102         * Gets the number of detected failures.
103         */
104        public synchronized int failureCount() {
105            return fFailures.size();
106        }
107    
108        /**
109         * Returns an Enumeration for the failures.
110         */
111        public synchronized Enumeration<TestFailure> failures() {
112            return Collections.enumeration(fFailures);
113        }
114    
115        /**
116         * Runs a TestCase.
117         */
118        protected void run(final TestCase test) {
119            startTest(test);
120            Protectable p = new Protectable() {
121                public void protect() throws Throwable {
122                    test.runBare();
123                }
124            };
125            runProtected(test, p);
126    
127            endTest(test);
128        }
129    
130        /**
131         * Gets the number of run tests.
132         */
133        public synchronized int runCount() {
134            return fRunTests;
135        }
136    
137        /**
138         * Runs a TestCase.
139         */
140        public void runProtected(final Test test, Protectable p) {
141            try {
142                p.protect();
143            } catch (AssertionFailedError e) {
144                addFailure(test, e);
145            } catch (ThreadDeath e) { // don't catch ThreadDeath by accident
146                throw e;
147            } catch (Throwable e) {
148                addError(test, e);
149            }
150        }
151    
152        /**
153         * Checks whether the test run should stop.
154         */
155        public synchronized boolean shouldStop() {
156            return fStop;
157        }
158    
159        /**
160         * Informs the result that a test will be started.
161         */
162        public void startTest(Test test) {
163            final int count = test.countTestCases();
164            synchronized (this) {
165                fRunTests += count;
166            }
167            for (TestListener each : cloneListeners()) {
168                each.startTest(test);
169            }
170        }
171    
172        /**
173         * Marks that the test run should stop.
174         */
175        public synchronized void stop() {
176            fStop = true;
177        }
178    
179        /**
180         * Returns whether the entire test was successful or not.
181         */
182        public synchronized boolean wasSuccessful() {
183            return failureCount() == 0 && errorCount() == 0;
184        }
185    }