    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    }