Skip to content

Commit a691962

Browse files
author
Tibor Digana
committed
#realUsage test, simplified
1 parent d2f1710 commit a691962

File tree

2 files changed

+62
-193
lines changed

2 files changed

+62
-193
lines changed

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

+3-7
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
import java.util.ArrayList;
44
import java.util.Arrays;
55
import java.util.Collection;
6-
import java.util.LinkedList;
76
import java.util.List;
8-
import java.util.concurrent.ConcurrentLinkedQueue;
7+
import java.util.concurrent.CopyOnWriteArrayList;
98
import org.junit.internal.AssumptionViolatedException;
109
import org.junit.runner.Description;
1110
import org.junit.runner.Result;
@@ -20,7 +19,7 @@
2019
* @since 4.0
2120
*/
2221
public class RunNotifier {
23-
private final ConcurrentLinkedQueue<RunListener> fListeners= new ConcurrentLinkedQueue<RunListener>();
22+
private final CopyOnWriteArrayList<RunListener> fListeners= new CopyOnWriteArrayList<RunListener>();
2423
private volatile boolean fPleaseStop= false;
2524

2625
/**
@@ -190,9 +189,6 @@ public void pleaseStop() {
190189
* Internal use only. The Result's listener must be first.
191190
*/
192191
public void addFirstListener(RunListener listener) {
193-
LinkedList<RunListener> listeners= new LinkedList<RunListener>(fListeners);
194-
listeners.addFirst(listener);
195-
fListeners.clear();
196-
fListeners.addAll(listeners);
192+
fListeners.add(0, listener);
197193
}
198194
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.junit.runner.notification;
22

3+
import java.util.concurrent.BrokenBarrierException;
34
import java.util.concurrent.Callable;
45
import java.util.concurrent.CyclicBarrier;
56
import java.util.concurrent.ExecutorService;
@@ -9,216 +10,98 @@
910
import java.util.concurrent.atomic.AtomicInteger;
1011
import org.junit.Test;
1112
import org.junit.runner.Description;
12-
import org.junit.runner.Result;
1313

1414
import static org.hamcrest.core.Is.is;
1515
import static org.junit.Assert.assertThat;
1616
import static org.junit.Assert.assertTrue;
1717

1818
/**
19-
* Testing RunNotifier with concurrent access.
19+
* Testing RunNotifier in concurrent access.
2020
* <p/>
2121
*
2222
* @author tibor17
23-
* @since 4.11
23+
* @version 4.12
24+
* @since 4.12
2425
*/
2526
public final class ConcurrentRunNotifierTest {
26-
private static final long TIMEOUT= 15;
27+
private static final long TIMEOUT = 3;
2728

2829
private static class ConcurrentRunListener extends RunListener {
29-
final AtomicInteger testRunStarted= new AtomicInteger(0);
30-
final AtomicInteger testRunFinished= new AtomicInteger(0);
31-
final AtomicInteger testStarted= new AtomicInteger(0);
32-
final AtomicInteger testFinished= new AtomicInteger(0);
33-
final AtomicInteger testFailure= new AtomicInteger(0);
34-
final AtomicInteger testAssumptionFailure= new AtomicInteger(0);
35-
final AtomicInteger testIgnored= new AtomicInteger(0);
36-
37-
public void testRunStarted(Description description) throws Exception {
38-
testRunStarted.incrementAndGet();
39-
}
40-
41-
public void testRunFinished(Result result) throws Exception {
42-
testRunFinished.incrementAndGet();
43-
}
30+
final AtomicInteger testStarted = new AtomicInteger(0);
4431

4532
public void testStarted(Description description) throws Exception {
4633
testStarted.incrementAndGet();
4734
}
48-
49-
public void testFinished(Description description) throws Exception {
50-
testFinished.incrementAndGet();
51-
}
52-
53-
public void testFailure(Failure failure) throws Exception {
54-
testFailure.incrementAndGet();
55-
}
56-
57-
public void testAssumptionFailure(Failure failure) {
58-
testAssumptionFailure.incrementAndGet();
59-
}
60-
61-
public void testIgnored(Description description) throws Exception {
62-
testIgnored.incrementAndGet();
63-
}
6435
}
6536

6637
@Test
67-
public void countDuplicatedListeners() throws InterruptedException {
68-
final int listenerCountPerEvent = 10;
69-
final ConcurrentRunListener examinedListener = new ConcurrentRunListener();
38+
public void realUsage() throws InterruptedException {
7039
final RunNotifier notifier = new RunNotifier();
71-
ExecutorService pool = Executors.newCachedThreadPool();
72-
for (int i = 0; i < listenerCountPerEvent; ++i) {
40+
41+
ConcurrentRunListener listener1 = new ConcurrentRunListener();
42+
ConcurrentRunListener listener2 = new ConcurrentRunListener();
43+
notifier.addListener(listener1);
44+
notifier.addListener(listener2);
45+
46+
final int numParallelTests = 4;
47+
ExecutorService pool = Executors.newFixedThreadPool(numParallelTests);
48+
for (int i = 0; i < numParallelTests; ++i) {
7349
pool.submit(new Runnable() {
7450
public void run() {
75-
notifier.addListener(examinedListener);
51+
notifier.fireTestStarted(null);
7652
}
7753
});
7854
}
7955
pool.shutdown();
8056
assertTrue(pool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
81-
notifier.fireTestRunStarted(null);
82-
notifier.fireTestRunFinished(null);
83-
notifier.fireTestStarted(null);
84-
notifier.fireTestFinished(null);
85-
notifier.fireTestFailure(null);
86-
notifier.fireTestAssumptionFailed(null);
87-
notifier.fireTestIgnored(null);
88-
assertThat(examinedListener.testRunStarted.get(), is(listenerCountPerEvent));
89-
assertThat(examinedListener.testRunFinished.get(), is(listenerCountPerEvent));
90-
assertThat(examinedListener.testStarted.get(), is(listenerCountPerEvent));
91-
assertThat(examinedListener.testFinished.get(), is(listenerCountPerEvent));
92-
assertThat(examinedListener.testFailure.get(), is(listenerCountPerEvent));
93-
assertThat(examinedListener.testAssumptionFailure.get(), is(listenerCountPerEvent));
94-
assertThat(examinedListener.testIgnored.get(), is(listenerCountPerEvent));
95-
}
9657

97-
@Test
98-
public void countUniqueListeners() throws InterruptedException {
99-
final ConcurrentRunListener[] examinedListeners = new ConcurrentRunListener[10];
100-
for (int i = 0; i < examinedListeners.length; ++i) {
101-
examinedListeners[i] = new ConcurrentRunListener();
102-
}
103-
final RunNotifier notifier = new RunNotifier();
104-
ExecutorService pool = Executors.newSingleThreadExecutor();
105-
pool.submit(new Runnable() {
106-
public void run() {
107-
for (ConcurrentRunListener examinedListener : examinedListeners) {
108-
notifier.addListener(examinedListener);
109-
}
110-
}
111-
});
112-
pool.shutdown();
113-
assertTrue(pool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
114-
115-
notifier.fireTestRunStarted(null);
116-
notifier.fireTestRunStarted(null);
117-
118-
notifier.fireTestRunFinished(null);
119-
notifier.fireTestRunFinished(null);
120-
121-
notifier.fireTestStarted(null);
122-
notifier.fireTestStarted(null);
123-
124-
notifier.fireTestFinished(null);
125-
notifier.fireTestFinished(null);
126-
127-
notifier.fireTestFailure(null);
128-
notifier.fireTestFailure(null);
58+
notifier.removeListener(listener1);
59+
notifier.removeListener(listener2);
12960

130-
notifier.fireTestAssumptionFailed(null);
131-
notifier.fireTestAssumptionFailed(null);
132-
133-
notifier.fireTestIgnored(null);
134-
notifier.fireTestIgnored(null);
135-
136-
for (ConcurrentRunListener examinedListener : examinedListeners) {
137-
assertThat(examinedListener.testRunStarted.get(), is(2));
138-
}
139-
140-
for (ConcurrentRunListener examinedListener : examinedListeners) {
141-
assertThat(examinedListener.testRunFinished.get(), is(2));
142-
}
143-
144-
for (ConcurrentRunListener examinedListener : examinedListeners) {
145-
assertThat(examinedListener.testStarted.get(), is(2));
146-
}
147-
148-
for (ConcurrentRunListener examinedListener : examinedListeners) {
149-
assertThat(examinedListener.testFinished.get(), is(2));
150-
}
151-
152-
for (ConcurrentRunListener examinedListener : examinedListeners) {
153-
assertThat(examinedListener.testFailure.get(), is(2));
154-
}
155-
156-
for (ConcurrentRunListener examinedListener : examinedListeners) {
157-
assertThat(examinedListener.testAssumptionFailure.get(), is(2));
158-
}
159-
160-
for (ConcurrentRunListener examinedListener : examinedListeners) {
161-
assertThat(examinedListener.testIgnored.get(), is(2));
162-
}
61+
assertThat(listener1.testStarted.get(), is(4));
62+
assertThat(listener2.testStarted.get(), is(4));
16363
}
16464

16565
private static class ExaminedListener extends RunListener {
166-
final AtomicBoolean testRunStarted= new AtomicBoolean(false);
16766
volatile boolean useMe = false;
16867
volatile boolean hasTestFailure = false;
16968

17069
ExaminedListener(boolean useMe) {
17170
this.useMe = useMe;
17271
}
17372

174-
public void testRunStarted(Description description) throws Exception {
175-
testRunStarted.set(true);
176-
if (!useMe) throw new Exception();
177-
}
178-
179-
public void testRunFinished(Result result) throws Exception {
180-
if (!useMe) throw new Exception();
181-
}
182-
18373
public void testStarted(Description description) throws Exception {
184-
if (!useMe) throw new Exception();
185-
}
186-
187-
public void testFinished(Description description) throws Exception {
188-
if (!useMe) throw new Exception();
74+
if (!useMe) {
75+
throw new Exception();
76+
}
18977
}
19078

19179
public void testFailure(Failure failure) throws Exception {
19280
hasTestFailure = true;
19381
}
194-
195-
public void testAssumptionFailure(Failure failure) {
196-
if (!useMe) throw new RuntimeException();
197-
}
198-
199-
public void testIgnored(Description description) throws Exception {
200-
if (!useMe) throw new Exception();
201-
}
20282
}
20383

204-
@Test @SuppressWarnings("unchecked")
205-
public void reportConcurrentFailuresAfterAddListener() throws InterruptedException {
84+
@Test
85+
@SuppressWarnings("unchecked")
86+
public void reportConcurrentFailuresAfterAddListener() throws InterruptedException, BrokenBarrierException {
20687
final RunNotifier notifier = new RunNotifier();
20788

20889
int totalListenersFailures = 0;
20990

21091
final ExaminedListener[] examinedListeners = new ExaminedListener[1000];
21192
for (int i = 0; i < examinedListeners.length; ++i) {
21293
boolean fail = StrictMath.random() >= 0.5d;
213-
if (fail) ++totalListenersFailures;
94+
if (fail) {
95+
++totalListenersFailures;
96+
}
21497
examinedListeners[i] = new ExaminedListener(!fail);
21598
}
21699

217100
final CyclicBarrier trigger = new CyclicBarrier(2);
218101
final AtomicBoolean condition = new AtomicBoolean(true);
219102

220-
ExecutorService callbacksPool = Executors.newSingleThreadExecutor();
221-
callbacksPool.submit(new Callable() {
103+
ExecutorService notificationsPool = Executors.newFixedThreadPool(4);
104+
notificationsPool.submit(new Callable() {
222105
public Object call() throws Exception {
223106
trigger.await();
224107
while (condition.get()) {
@@ -229,23 +112,15 @@ public Object call() throws Exception {
229112
}
230113
});
231114

232-
ExecutorService listenersPool = Executors.newSingleThreadExecutor();
233-
listenersPool.submit(new Callable() {
234-
public Object call() throws Exception {
235-
trigger.await();
236-
for (ExaminedListener examinedListener : examinedListeners) {
237-
notifier.addListener(examinedListener);
238-
}
239-
return null;
240-
}
241-
});
115+
trigger.await();
242116

243-
callbacksPool.shutdown();
244-
listenersPool.shutdown();
117+
for (ExaminedListener examinedListener : examinedListeners) {
118+
notifier.addListener(examinedListener);
119+
}
245120

246-
assertTrue(listenersPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
121+
notificationsPool.shutdown();
247122
condition.set(false);
248-
assertTrue(callbacksPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
123+
assertTrue(notificationsPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
249124

250125
if (totalListenersFailures != 0) {
251126
// If no listener failures, then all the listeners do not report any failure.
@@ -254,24 +129,27 @@ public Object call() throws Exception {
254129
}
255130
}
256131

257-
@Test @SuppressWarnings("unchecked")
258-
public void reportConcurrentFailuresAfterAddFirstListener() throws InterruptedException {
132+
@Test
133+
@SuppressWarnings("unchecked")
134+
public void reportConcurrentFailuresAfterAddFirstListener() throws InterruptedException, BrokenBarrierException {
259135
final RunNotifier notifier = new RunNotifier();
260136

261137
int totalListenersFailures = 0;
262138

263-
final ExaminedListener[] examinedListeners = new ExaminedListener[100];
139+
final ExaminedListener[] examinedListeners = new ExaminedListener[1000];
264140
for (int i = 0; i < examinedListeners.length; ++i) {
265141
boolean fail = StrictMath.random() >= 0.5d;
266-
if (fail) ++totalListenersFailures;
142+
if (fail) {
143+
++totalListenersFailures;
144+
}
267145
examinedListeners[i] = new ExaminedListener(!fail);
268146
}
269147

270148
final CyclicBarrier trigger = new CyclicBarrier(2);
271149
final AtomicBoolean condition = new AtomicBoolean(true);
272150

273-
ExecutorService callbacksPool = Executors.newSingleThreadExecutor();
274-
callbacksPool.submit(new Callable() {
151+
ExecutorService notificationsPool = Executors.newFixedThreadPool(4);
152+
notificationsPool.submit(new Callable() {
275153
public Object call() throws Exception {
276154
trigger.await();
277155
while (condition.get()) {
@@ -282,23 +160,15 @@ public Object call() throws Exception {
282160
}
283161
});
284162

285-
ExecutorService listenersPool = Executors.newSingleThreadExecutor();
286-
listenersPool.submit(new Callable() {
287-
public Object call() throws Exception {
288-
trigger.await();
289-
for (ExaminedListener examinedListener : examinedListeners) {
290-
notifier.addFirstListener(examinedListener);
291-
}
292-
return null;
293-
}
294-
});
163+
trigger.await();
295164

296-
callbacksPool.shutdown();
297-
listenersPool.shutdown();
165+
for (ExaminedListener examinedListener : examinedListeners) {
166+
notifier.addFirstListener(examinedListener);
167+
}
298168

299-
assertTrue(listenersPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
169+
notificationsPool.shutdown();
300170
condition.set(false);
301-
assertTrue(callbacksPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
171+
assertTrue(notificationsPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));
302172

303173
if (totalListenersFailures != 0) {
304174
// If no listener failures, then all the listeners do not report any failure.
@@ -308,9 +178,12 @@ public Object call() throws Exception {
308178
}
309179

310180
private static int countReportedTestFailures(ExaminedListener[] listeners) {
311-
int count= 0;
312-
for (ExaminedListener listener : listeners)
313-
if (listener.hasTestFailure) ++count;
181+
int count = 0;
182+
for (ExaminedListener listener : listeners) {
183+
if (listener.hasTestFailure) {
184+
++count;
185+
}
186+
}
314187
return count;
315188
}
316189
}

0 commit comments

Comments
 (0)