001    package org.junit.runners.model;
002    
003    import java.io.PrintStream;
004    import java.io.PrintWriter;
005    import java.util.ArrayList;
006    import java.util.Collections;
007    import java.util.List;
008    
009    import org.junit.TestCouldNotBeSkippedException;
010    import org.junit.internal.AssumptionViolatedException;
011    import org.junit.internal.Throwables;
012    
013    /**
014     * Collects multiple {@code Throwable}s into one exception.
015     *
016     * @since 4.9
017     */
018    public class MultipleFailureException extends Exception {
019        private static final long serialVersionUID = 1L;
020    
021        /*
022         * We have to use the f prefix until the next major release to ensure
023         * serialization compatibility. 
024         * See https://github.com/junit-team/junit4/issues/976
025         */
026        private final List<Throwable> fErrors;
027    
028        public MultipleFailureException(List<Throwable> errors) {
029            if (errors.isEmpty()) {
030                throw new IllegalArgumentException(
031                        "List of Throwables must not be empty");
032            }
033            this.fErrors = new ArrayList<Throwable>(errors.size());
034            for (Throwable error : errors) {
035                if (error instanceof AssumptionViolatedException) {
036                    error = new TestCouldNotBeSkippedException((AssumptionViolatedException) error);
037                }
038                fErrors.add(error);
039            }
040        }
041    
042        public List<Throwable> getFailures() {
043            return Collections.unmodifiableList(fErrors);
044        }
045    
046        @Override
047        public String getMessage() {
048            StringBuilder sb = new StringBuilder(
049                    String.format("There were %d errors:", fErrors.size()));
050            for (Throwable e : fErrors) {
051                sb.append(String.format("%n  %s(%s)", e.getClass().getName(), e.getMessage()));
052            }
053            return sb.toString();
054        }
055    
056        @Override
057        public void printStackTrace() {
058            for (Throwable e: fErrors) {
059                e.printStackTrace();
060            }
061        }
062        
063        @Override
064        public void printStackTrace(PrintStream s) {
065            for (Throwable e: fErrors) {
066                e.printStackTrace(s);
067            }
068        }
069        
070        @Override
071        public void printStackTrace(PrintWriter s) {
072            for (Throwable e: fErrors) {
073                e.printStackTrace(s);
074            }
075        }
076        
077        /**
078         * Asserts that a list of throwables is empty. If it isn't empty,
079         * will throw {@link MultipleFailureException} (if there are
080         * multiple throwables in the list) or the first element in the list
081         * (if there is only one element).
082         *
083         * @param errors list to check
084         * @throws Exception or Error if the list is not empty
085         */
086        @SuppressWarnings("deprecation")
087        public static void assertEmpty(List<Throwable> errors) throws Exception {
088            if (errors.isEmpty()) {
089                return;
090            }
091            if (errors.size() == 1) {
092                throw Throwables.rethrowAsException(errors.get(0));
093            }
094    
095            /*
096               * Many places in the code are documented to throw
097               * org.junit.internal.runners.model.MultipleFailureException.
098               * That class now extends this one, so we throw the internal
099               * exception in case developers have tests that catch
100               * MultipleFailureException.
101               */
102            throw new org.junit.internal.runners.model.MultipleFailureException(errors);
103        }
104    }