1
1
package org .junit .runner .notification ;
2
2
3
+ import java .util .concurrent .BrokenBarrierException ;
3
4
import java .util .concurrent .Callable ;
4
5
import java .util .concurrent .CyclicBarrier ;
5
6
import java .util .concurrent .ExecutorService ;
9
10
import java .util .concurrent .atomic .AtomicInteger ;
10
11
import org .junit .Test ;
11
12
import org .junit .runner .Description ;
12
- import org .junit .runner .Result ;
13
13
14
14
import static org .hamcrest .core .Is .is ;
15
15
import static org .junit .Assert .assertThat ;
16
16
import static org .junit .Assert .assertTrue ;
17
17
18
18
/**
19
- * Testing RunNotifier with concurrent access.
19
+ * Testing RunNotifier in concurrent access.
20
20
* <p/>
21
21
*
22
22
* @author tibor17
23
- * @since 4.11
23
+ * @version 4.12
24
+ * @since 4.12
24
25
*/
25
26
public final class ConcurrentRunNotifierTest {
26
- private static final long TIMEOUT = 15 ;
27
+ private static final long TIMEOUT = 3 ;
27
28
28
29
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 );
44
31
45
32
public void testStarted (Description description ) throws Exception {
46
33
testStarted .incrementAndGet ();
47
34
}
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
- }
64
35
}
65
36
66
37
@ Test
67
- public void countDuplicatedListeners () throws InterruptedException {
68
- final int listenerCountPerEvent = 10 ;
69
- final ConcurrentRunListener examinedListener = new ConcurrentRunListener ();
38
+ public void realUsage () throws InterruptedException {
70
39
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 ) {
73
49
pool .submit (new Runnable () {
74
50
public void run () {
75
- notifier .addListener ( examinedListener );
51
+ notifier .fireTestStarted ( null );
76
52
}
77
53
});
78
54
}
79
55
pool .shutdown ();
80
56
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
- }
96
57
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 );
129
60
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 ));
163
63
}
164
64
165
65
private static class ExaminedListener extends RunListener {
166
- final AtomicBoolean testRunStarted = new AtomicBoolean (false );
167
66
volatile boolean useMe = false ;
168
67
volatile boolean hasTestFailure = false ;
169
68
170
69
ExaminedListener (boolean useMe ) {
171
70
this .useMe = useMe ;
172
71
}
173
72
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
-
183
73
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
+ }
189
77
}
190
78
191
79
public void testFailure (Failure failure ) throws Exception {
192
80
hasTestFailure = true ;
193
81
}
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
- }
202
82
}
203
83
204
- @ Test @ SuppressWarnings ("unchecked" )
205
- public void reportConcurrentFailuresAfterAddListener () throws InterruptedException {
84
+ @ Test
85
+ @ SuppressWarnings ("unchecked" )
86
+ public void reportConcurrentFailuresAfterAddListener () throws InterruptedException , BrokenBarrierException {
206
87
final RunNotifier notifier = new RunNotifier ();
207
88
208
89
int totalListenersFailures = 0 ;
209
90
210
91
final ExaminedListener [] examinedListeners = new ExaminedListener [1000 ];
211
92
for (int i = 0 ; i < examinedListeners .length ; ++i ) {
212
93
boolean fail = StrictMath .random () >= 0.5d ;
213
- if (fail ) ++totalListenersFailures ;
94
+ if (fail ) {
95
+ ++totalListenersFailures ;
96
+ }
214
97
examinedListeners [i ] = new ExaminedListener (!fail );
215
98
}
216
99
217
100
final CyclicBarrier trigger = new CyclicBarrier (2 );
218
101
final AtomicBoolean condition = new AtomicBoolean (true );
219
102
220
- ExecutorService callbacksPool = Executors .newSingleThreadExecutor ( );
221
- callbacksPool .submit (new Callable () {
103
+ ExecutorService notificationsPool = Executors .newFixedThreadPool ( 4 );
104
+ notificationsPool .submit (new Callable () {
222
105
public Object call () throws Exception {
223
106
trigger .await ();
224
107
while (condition .get ()) {
@@ -229,23 +112,15 @@ public Object call() throws Exception {
229
112
}
230
113
});
231
114
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 ();
242
116
243
- callbacksPool .shutdown ();
244
- listenersPool .shutdown ();
117
+ for (ExaminedListener examinedListener : examinedListeners ) {
118
+ notifier .addListener (examinedListener );
119
+ }
245
120
246
- assertTrue ( listenersPool . awaitTermination ( TIMEOUT , TimeUnit . SECONDS ) );
121
+ notificationsPool . shutdown ( );
247
122
condition .set (false );
248
- assertTrue (callbacksPool .awaitTermination (TIMEOUT , TimeUnit .SECONDS ));
123
+ assertTrue (notificationsPool .awaitTermination (TIMEOUT , TimeUnit .SECONDS ));
249
124
250
125
if (totalListenersFailures != 0 ) {
251
126
// If no listener failures, then all the listeners do not report any failure.
@@ -254,24 +129,27 @@ public Object call() throws Exception {
254
129
}
255
130
}
256
131
257
- @ Test @ SuppressWarnings ("unchecked" )
258
- public void reportConcurrentFailuresAfterAddFirstListener () throws InterruptedException {
132
+ @ Test
133
+ @ SuppressWarnings ("unchecked" )
134
+ public void reportConcurrentFailuresAfterAddFirstListener () throws InterruptedException , BrokenBarrierException {
259
135
final RunNotifier notifier = new RunNotifier ();
260
136
261
137
int totalListenersFailures = 0 ;
262
138
263
- final ExaminedListener [] examinedListeners = new ExaminedListener [100 ];
139
+ final ExaminedListener [] examinedListeners = new ExaminedListener [1000 ];
264
140
for (int i = 0 ; i < examinedListeners .length ; ++i ) {
265
141
boolean fail = StrictMath .random () >= 0.5d ;
266
- if (fail ) ++totalListenersFailures ;
142
+ if (fail ) {
143
+ ++totalListenersFailures ;
144
+ }
267
145
examinedListeners [i ] = new ExaminedListener (!fail );
268
146
}
269
147
270
148
final CyclicBarrier trigger = new CyclicBarrier (2 );
271
149
final AtomicBoolean condition = new AtomicBoolean (true );
272
150
273
- ExecutorService callbacksPool = Executors .newSingleThreadExecutor ( );
274
- callbacksPool .submit (new Callable () {
151
+ ExecutorService notificationsPool = Executors .newFixedThreadPool ( 4 );
152
+ notificationsPool .submit (new Callable () {
275
153
public Object call () throws Exception {
276
154
trigger .await ();
277
155
while (condition .get ()) {
@@ -282,23 +160,15 @@ public Object call() throws Exception {
282
160
}
283
161
});
284
162
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 ();
295
164
296
- callbacksPool .shutdown ();
297
- listenersPool .shutdown ();
165
+ for (ExaminedListener examinedListener : examinedListeners ) {
166
+ notifier .addFirstListener (examinedListener );
167
+ }
298
168
299
- assertTrue ( listenersPool . awaitTermination ( TIMEOUT , TimeUnit . SECONDS ) );
169
+ notificationsPool . shutdown ( );
300
170
condition .set (false );
301
- assertTrue (callbacksPool .awaitTermination (TIMEOUT , TimeUnit .SECONDS ));
171
+ assertTrue (notificationsPool .awaitTermination (TIMEOUT , TimeUnit .SECONDS ));
302
172
303
173
if (totalListenersFailures != 0 ) {
304
174
// If no listener failures, then all the listeners do not report any failure.
@@ -308,9 +178,12 @@ public Object call() throws Exception {
308
178
}
309
179
310
180
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
+ }
314
187
return count ;
315
188
}
316
189
}
0 commit comments