1package org.junit.rules;
2
3import static org.junit.Assert.assertThat;
4
5import java.util.ArrayList;
6import java.util.List;
7import java.util.concurrent.Callable;
8
9import org.hamcrest.Matcher;
10import org.junit.runners.model.MultipleFailureException;
11
12/**
13 * The ErrorCollector rule allows execution of a test to continue after the
14 * first problem is found (for example, to collect _all_ the incorrect rows in a
15 * table, and report them all at once):
16 *
17 * <pre>
18 * public static class UsesErrorCollectorTwice {
19 * 	&#064;Rule
20 * 	public ErrorCollector collector= new ErrorCollector();
21 *
22 * &#064;Test
23 * public void example() {
24 *      collector.addError(new Throwable(&quot;first thing went wrong&quot;));
25 *      collector.addError(new Throwable(&quot;second thing went wrong&quot;));
26 *      collector.checkThat(getResult(), not(containsString(&quot;ERROR!&quot;)));
27 *      // all lines will run, and then a combined failure logged at the end.
28 *     }
29 * }
30 * </pre>
31 *
32 * @since 4.7
33 */
34public class ErrorCollector extends Verifier {
35    private List<Throwable> errors = new ArrayList<Throwable>();
36
37    @Override
38    protected void verify() throws Throwable {
39        MultipleFailureException.assertEmpty(errors);
40    }
41
42    /**
43     * Adds a Throwable to the table.  Execution continues, but the test will fail at the end.
44     */
45    public void addError(Throwable error) {
46        errors.add(error);
47    }
48
49    /**
50     * Adds a failure to the table if {@code matcher} does not match {@code value}.
51     * Execution continues, but the test will fail at the end if the match fails.
52     */
53    public <T> void checkThat(final T value, final Matcher<T> matcher) {
54        checkThat("", value, matcher);
55    }
56
57    /**
58     * Adds a failure with the given {@code reason}
59     * to the table if {@code matcher} does not match {@code value}.
60     * Execution continues, but the test will fail at the end if the match fails.
61     */
62    public <T> void checkThat(final String reason, final T value, final Matcher<T> matcher) {
63        checkSucceeds(new Callable<Object>() {
64            public Object call() throws Exception {
65                assertThat(reason, value, matcher);
66                return value;
67            }
68        });
69    }
70
71    /**
72     * Adds to the table the exception, if any, thrown from {@code callable}.
73     * Execution continues, but the test will fail at the end if
74     * {@code callable} threw an exception.
75     */
76    public <T> T checkSucceeds(Callable<T> callable) {
77        try {
78            return callable.call();
79        } catch (Throwable e) {
80            addError(e);
81            return null;
82        }
83    }
84}
85