001package org.junit.runners.model;
002
003import java.io.PrintStream;
004import java.io.PrintWriter;
005import java.util.ArrayList;
006import java.util.Collections;
007import java.util.List;
008
009import org.junit.TestCouldNotBeSkippedException;
010import org.junit.internal.AssumptionViolatedException;
011import org.junit.internal.Throwables;
012
013/**
014 * Collects multiple {@code Throwable}s into one exception.
015 *
016 * @since 4.9
017 */
018public 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}