Skip to content

Commit a400a3a

Browse files
committed
Move wrapIfNotThreadSafe() to RunNotifier
1 parent 38ac72e commit a400a3a

File tree

4 files changed

+51
-57
lines changed

4 files changed

+51
-57
lines changed

src/main/java/org/junit/runner/notification/RunNotifier.java

+14-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public void addListener(RunListener listener) {
3131
if (listener == null) {
3232
throw new NullPointerException("Cannot add a null listener");
3333
}
34-
fListeners.add(SynchronizedRunListener.wrapIfNotThreadSafe(listener));
34+
fListeners.add(wrapIfNotThreadSafe(listener));
3535
}
3636

3737
/**
@@ -41,9 +41,19 @@ public void removeListener(RunListener listener) {
4141
if (listener == null) {
4242
throw new NullPointerException("Cannot remove a null listener");
4343
}
44-
fListeners.remove(SynchronizedRunListener.wrapIfNotThreadSafe(listener));
44+
fListeners.remove(wrapIfNotThreadSafe(listener));
4545
}
4646

47+
/**
48+
* Wraps the given listener with {@link SynchronizedRunListener} if
49+
* it is not annotated with {@link RunListener.ThreadSafe}.
50+
*/
51+
RunListener wrapIfNotThreadSafe(RunListener listener) {
52+
return listener.getClass().isAnnotationPresent(RunListener.ThreadSafe.class) ?
53+
listener : new SynchronizedRunListener(listener, this);
54+
}
55+
56+
4757
private abstract class SafeNotifier {
4858
private final List<RunListener> fCurrentListeners;
4959

@@ -52,7 +62,7 @@ private abstract class SafeNotifier {
5262
}
5363

5464
SafeNotifier(List<RunListener> currentListeners) {
55-
this.fCurrentListeners = currentListeners;
65+
fCurrentListeners = currentListeners;
5666
}
5767

5868
void run() {
@@ -201,6 +211,6 @@ public void addFirstListener(RunListener listener) {
201211
if (listener == null) {
202212
throw new NullPointerException("Cannot add a null listener");
203213
}
204-
fListeners.add(0, SynchronizedRunListener.wrapIfNotThreadSafe(listener));
214+
fListeners.add(0, wrapIfNotThreadSafe(listener));
205215
}
206216
}

src/main/java/org/junit/runner/notification/SynchronizedRunListener.java

+13-21
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Thread-safe decorator for {@link RunListener} implementations that synchronizes
88
* calls to the delegate.
99
*
10-
* <p>This class synchronizes all listener calls on a global monitor. This is done because
10+
* <p>This class synchronizes all listener calls on a RunNotifier instance. This is done because
1111
* prior to JUnit 4.12, all listeners were called in a synchronized block in RunNotifier,
1212
* so no two listeners were ever called concurrently. If we instead made the methods here
1313
* sychronized, clients that added multiple listeners that called common code might see
@@ -21,67 +21,59 @@
2121
*/
2222
@RunListener.ThreadSafe
2323
final class SynchronizedRunListener extends RunListener {
24-
private static final Object sMonitor = new Object();
2524
private final RunListener fListener;
25+
private final Object fMonitor;
2626

27-
/**
28-
* Wraps the given listener with {@link SynchronizedRunListener} if
29-
* it is not annotated with {@link RunListener.ThreadSafe}.
30-
*/
31-
public static RunListener wrapIfNotThreadSafe(RunListener listener) {
32-
return listener.getClass().isAnnotationPresent(RunListener.ThreadSafe.class) ?
33-
listener : new SynchronizedRunListener(listener);
34-
}
35-
36-
SynchronizedRunListener(RunListener listener) {
37-
this.fListener = listener;
27+
SynchronizedRunListener(RunListener listener, Object monitor) {
28+
fListener = listener;
29+
fMonitor = monitor;
3830
}
3931

4032
@Override
4133
public void testRunStarted(Description description) throws Exception {
42-
synchronized (sMonitor) {
34+
synchronized (fMonitor) {
4335
fListener.testRunStarted(description);
4436
}
4537
}
4638

4739
@Override
4840
public void testRunFinished(Result result) throws Exception {
49-
synchronized (sMonitor) {
41+
synchronized (fMonitor) {
5042
fListener.testRunFinished(result);
5143
}
5244
}
5345

5446
@Override
5547
public void testStarted(Description description) throws Exception {
56-
synchronized (sMonitor) {
48+
synchronized (fMonitor) {
5749
fListener.testStarted(description);
5850
}
5951
}
6052

6153
@Override
6254
public void testFinished(Description description) throws Exception {
63-
synchronized (sMonitor) {
55+
synchronized (fMonitor) {
6456
fListener.testFinished(description);
6557
}
6658
}
6759

6860
@Override
6961
public void testFailure(Failure failure) throws Exception {
70-
synchronized (sMonitor) {
62+
synchronized (fMonitor) {
7163
fListener.testFailure(failure);
7264
}
7365
}
7466

7567
@Override
7668
public void testAssumptionFailure(Failure failure) {
77-
synchronized (sMonitor) {
69+
synchronized (fMonitor) {
7870
fListener.testAssumptionFailure(failure);
7971
}
8072
}
8173

8274
@Override
8375
public void testIgnored(Description description) throws Exception {
84-
synchronized (sMonitor) {
76+
synchronized (fMonitor) {
8577
fListener.testIgnored(description);
8678
}
8779
}
@@ -101,7 +93,7 @@ public boolean equals(Object other) {
10193
}
10294
SynchronizedRunListener that = (SynchronizedRunListener) other;
10395

104-
return this.fListener.equals(that.fListener);
96+
return fListener.equals(that.fListener);
10597
}
10698

10799
@Override

src/test/java/org/junit/runner/notification/RunNotifierTest.java

+15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.junit.runner.notification;
22

3+
import static org.hamcrest.CoreMatchers.instanceOf;
34
import static org.hamcrest.core.Is.is;
45
import static org.junit.Assert.assertNotNull;
6+
import static org.junit.Assert.assertSame;
57
import static org.junit.Assert.assertThat;
68

79
import java.util.concurrent.atomic.AtomicInteger;
@@ -91,6 +93,19 @@ public void addFirstAndRemoveWithThreadSafeListener() {
9193
assertThat(listener.fTestStarted.get(), is(1));
9294
}
9395

96+
@Test
97+
public void wrapIfNotThreadSafeShouldNotWrapThreadSafeListeners() {
98+
ThreadSafeListener listener = new ThreadSafeListener();;
99+
assertSame(listener, new RunNotifier().wrapIfNotThreadSafe(listener));
100+
}
101+
102+
@Test
103+
public void wrapIfNotThreadSafeShouldWrapNonThreadSafeListeners() {
104+
CountingListener listener = new CountingListener();
105+
RunListener wrappedListener = new RunNotifier().wrapIfNotThreadSafe(listener);
106+
assertThat(wrappedListener, instanceOf(SynchronizedRunListener.class));
107+
}
108+
94109
private static class FailureListener extends RunListener {
95110
private Failure failure;
96111

src/test/java/org/junit/runner/notification/SynchronizedRunListenerTest.java

+9-32
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package org.junit.runner.notification;
22

3-
import static org.hamcrest.CoreMatchers.instanceOf;
43
import static org.junit.Assert.assertEquals;
54
import static org.junit.Assert.assertFalse;
65
import static org.junit.Assert.assertNotEquals;
7-
import static org.junit.Assert.assertSame;
86
import static org.junit.Assert.assertThat;
97
import static org.junit.Assert.assertTrue;
108

@@ -104,10 +102,6 @@ public boolean equals(Object obj) {
104102
}
105103
}
106104

107-
@RunListener.ThreadSafe
108-
private static class ThreadSafeRunListener extends RunListener {
109-
}
110-
111105
@Test
112106
public void namedListenerCorrectlyImplementsEqualsAndHashCode() {
113107
NamedListener listener1 = new NamedListener("blue");
@@ -135,7 +129,7 @@ public void toStringDelegates() {
135129
NamedListener listener = new NamedListener("blue");
136130

137131
assertEquals("NamedListener", listener.toString());
138-
assertEquals("NamedListener (with synchronization wrapper)", new SynchronizedRunListener(listener).toString());
132+
assertEquals("NamedListener (with synchronization wrapper)", wrap(listener).toString());
139133
}
140134

141135
@Test
@@ -144,37 +138,20 @@ public void equalsDelegates() {
144138
NamedListener listener2 = new NamedListener("blue");
145139
NamedListener listener3 = new NamedListener("red");
146140

147-
assertEquals(new SynchronizedRunListener(listener1),
148-
new SynchronizedRunListener(listener1));
149-
assertEquals(new SynchronizedRunListener(listener1),
150-
new SynchronizedRunListener(listener2));
151-
assertNotEquals(new SynchronizedRunListener(listener1),
152-
new SynchronizedRunListener(listener3));
153-
assertNotEquals(new SynchronizedRunListener(listener1), listener1);
154-
assertNotEquals(listener1, new SynchronizedRunListener(listener1));
141+
assertEquals(wrap(listener1), wrap(listener1));
142+
assertEquals(wrap(listener1), wrap(listener2));
143+
assertNotEquals(wrap(listener1), wrap(listener3));
144+
assertNotEquals(wrap(listener1), listener1);
145+
assertNotEquals(listener1, wrap(listener1));
155146
}
156147

157148
@Test
158149
public void hashCodeDelegates() {
159150
NamedListener listener = new NamedListener("blue");
160-
assertEquals(listener.hashCode(), new SynchronizedRunListener(listener).hashCode());
161-
}
162-
163-
@Test
164-
public void wrapIfNotThreadSafeShouldNotWrapThreadSafeListeners() {
165-
ThreadSafeRunListener listener = new ThreadSafeRunListener();;
166-
assertSame(listener, SynchronizedRunListener.wrapIfNotThreadSafe(listener));
151+
assertEquals(listener.hashCode(), wrap(listener).hashCode());
167152
}
168153

169-
/**
170-
* Tests that {@link SynchronizedRunListener#wrapIfNotThreadSafe(RunListener)}
171-
* wraps listeners that are not thread-safe. This does not check if the
172-
* listener is synchronized; that is tested with the tests for {@link RunNotifier}.
173-
*/
174-
@Test
175-
public void wrapIfNotThreadSafeShouldWrapNonThreadSafeListeners() {
176-
NamedListener listener = new NamedListener("name");
177-
RunListener wrappedListener = SynchronizedRunListener.wrapIfNotThreadSafe(listener);
178-
assertThat(wrappedListener, instanceOf(SynchronizedRunListener.class));
154+
private SynchronizedRunListener wrap(RunListener listener) {
155+
return new SynchronizedRunListener(listener, this);
179156
}
180157
}

0 commit comments

Comments
 (0)