aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/junit/runner/notification/SynchronizedRunListener.java
blob: 400fed8fcebff576e71ccce61372ec5dd7b1b313 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package org.junit.runner.notification;

import org.junit.runner.Description;
import org.junit.runner.Result;

/**
 * Thread-safe decorator for {@link RunListener} implementations that synchronizes
 * calls to the delegate.
 *
 * <p>This class synchronizes all listener calls on a RunNotifier instance. This is done because
 * prior to JUnit 4.12, all listeners were called in a synchronized block in RunNotifier,
 * so no two listeners were ever called concurrently. If we instead made the methods here
 * synchronized, clients that added multiple listeners that called common code might see
 * issues due to the reduced synchronization.
 *
 * @author Tibor Digana (tibor17)
 * @author Kevin Cooney (kcooney)
 * @since 4.12
 *
 * @see RunNotifier
 */
@RunListener.ThreadSafe
final class SynchronizedRunListener extends RunListener {
    private final RunListener listener;
    private final Object monitor;

    SynchronizedRunListener(RunListener listener, Object monitor) {
        this.listener = listener;
        this.monitor = monitor;
    }

    @Override
    public void testRunStarted(Description description) throws Exception {
        synchronized (monitor) {
            listener.testRunStarted(description);
        }
    }

    @Override
    public void testRunFinished(Result result) throws Exception {
        synchronized (monitor) {
            listener.testRunFinished(result);
        }
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Synchronized decorator for {@link RunListener#testSuiteStarted(Description)}.
     * @param description the description of the test suite that is about to be run
     *                    (generally a class name).
     * @throws Exception if any occurs.
     * @since 4.13
     */
    @Override
    public void testSuiteStarted(Description description) throws Exception {
        synchronized (monitor) {
            listener.testSuiteStarted(description);
        }
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Synchronized decorator for {@link RunListener#testSuiteFinished(Description)}.
     * @param description the description of the test suite that just ran.
     * @throws Exception
     * @since 4.13
     */
    @Override
    public void testSuiteFinished(Description description) throws Exception {
        synchronized (monitor) {
            listener.testSuiteFinished(description);
        }
    }

    @Override
    public void testStarted(Description description) throws Exception {
        synchronized (monitor) {
            listener.testStarted(description);
        }
    }

    @Override
    public void testFinished(Description description) throws Exception {
        synchronized (monitor) {
            listener.testFinished(description);
        }
    }

    @Override
    public void testFailure(Failure failure) throws Exception {
        synchronized (monitor) {
            listener.testFailure(failure);
        }
    }

    @Override
    public void testAssumptionFailure(Failure failure) {
        synchronized (monitor) {
            listener.testAssumptionFailure(failure);
        }
    }

    @Override
    public void testIgnored(Description description) throws Exception {
        synchronized (monitor) {
            listener.testIgnored(description);
        }
    }

    @Override
    public int hashCode() {
        return listener.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof SynchronizedRunListener)) {
            return false;
        }
        SynchronizedRunListener that = (SynchronizedRunListener) other;
        
        return listener.equals(that.listener);
    }

    @Override
    public String toString() {
        return listener.toString() + " (with synchronization wrapper)";
    }
}