Skip to content

Commit 5ab051d

Browse files
committed
Check that test classes are executed concurrently
1 parent 0199187 commit 5ab051d

File tree

2 files changed

+42
-247
lines changed

2 files changed

+42
-247
lines changed

junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/ParallelExecutionIntegrationTests.java

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,20 @@
1111
package org.junit.vintage.engine.execution;
1212

1313
import static org.assertj.core.api.Assertions.assertThat;
14+
import static org.junit.platform.testkit.engine.EventConditions.container;
1415
import static org.junit.platform.testkit.engine.EventConditions.event;
1516
import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully;
16-
import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure;
1717
import static org.junit.platform.testkit.engine.EventConditions.started;
18-
import static org.junit.platform.testkit.engine.EventConditions.test;
19-
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.AtomicOperationParallelTestCase;
20-
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.ConcurrentFailureTestCase;
21-
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.ConcurrentIncrementTestCase;
22-
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.FailingParallelTestCase;
23-
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.ParallelFailingTestCase;
24-
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.SuccessfulParallelTestCase;
18+
import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_RUNNER;
19+
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.AbstractBlockingTestCase;
20+
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.FirstTestCase;
21+
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.ThirdTestCase;
2522

2623
import java.time.Instant;
2724
import java.util.Arrays;
2825
import java.util.HashSet;
2926
import java.util.List;
30-
import java.util.Set;
27+
import java.util.concurrent.CountDownLatch;
3128

3229
import org.assertj.core.api.Condition;
3330
import org.junit.jupiter.api.Test;
@@ -41,45 +38,33 @@
4138
import org.junit.platform.testkit.engine.Event;
4239
import org.junit.platform.testkit.engine.Events;
4340
import org.junit.vintage.engine.VintageTestEngine;
41+
import org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.SecondTestCase;
4442

4543
class ParallelExecutionIntegrationTests {
4644

4745
private static final String PARALLEL_EXECUTION_ENABLED = "junit.vintage.execution.parallel.enabled";
4846
private static final String PARALLEL_POOL_SIZE = "junit.vintage.execution.parallel.pool-size";
4947

5048
@Test
51-
void successfulParallelTest(TestReporter reporter) {
52-
var events = executeInParallelSuccessfully(3, SuccessfulParallelTestCase.class,
53-
ConcurrentIncrementTestCase.class, AtomicOperationParallelTestCase.class).list();
49+
void executesTestClassesInParallel(TestReporter reporter) {
50+
AbstractBlockingTestCase.threadNames.clear();
51+
AbstractBlockingTestCase.countDownLatch = new CountDownLatch(3);
5452

55-
var startedTimestamps = getTimestampsFor(events, event(test(), started()));
56-
var finishedTimestamps = getTimestampsFor(events, event(test(), finishedSuccessfully()));
57-
var threadNames = new HashSet<>(Set.of(SuccessfulParallelTestCase.threadNames,
58-
ConcurrentIncrementTestCase.threadNames, AtomicOperationParallelTestCase.threadNames));
53+
var events = executeInParallelSuccessfully(3, FirstTestCase.class, SecondTestCase.class,
54+
ThirdTestCase.class).list();
5955

60-
reporter.publishEntry("startedTimestamps", startedTimestamps.toString());
61-
reporter.publishEntry("finishedTimestamps", finishedTimestamps.toString());
62-
63-
assertThat(startedTimestamps).hasSize(9);
64-
assertThat(finishedTimestamps).hasSize(9);
65-
assertThat(threadNames).hasSize(3);
66-
}
67-
68-
@Test
69-
void failingParallelTest(TestReporter reporter) {
70-
var events = executeInParallel(3, FailingParallelTestCase.class, ConcurrentFailureTestCase.class,
71-
ParallelFailingTestCase.class).list();
72-
73-
var startedTimestamps = getTimestampsFor(events, event(test(), started()));
74-
var finishedTimestamps = getTimestampsFor(events, event(test(), finishedWithFailure()));
75-
var threadNames = new HashSet<>(Set.of(FailingParallelTestCase.threadNames,
76-
ConcurrentFailureTestCase.threadNames, ParallelFailingTestCase.threadNames));
56+
var startedTimestamps = getTimestampsFor(events, event(container(SEGMENT_TYPE_RUNNER), started()));
57+
var finishedTimestamps = getTimestampsFor(events,
58+
event(container(SEGMENT_TYPE_RUNNER), finishedSuccessfully()));
59+
var threadNames = new HashSet<>(AbstractBlockingTestCase.threadNames);
7760

7861
reporter.publishEntry("startedTimestamps", startedTimestamps.toString());
7962
reporter.publishEntry("finishedTimestamps", finishedTimestamps.toString());
8063

81-
assertThat(startedTimestamps).hasSize(9);
82-
assertThat(finishedTimestamps).hasSize(9);
64+
assertThat(startedTimestamps).hasSize(3);
65+
assertThat(finishedTimestamps).hasSize(3);
66+
assertThat(startedTimestamps).allMatch(startTimestamp -> finishedTimestamps.stream().noneMatch(
67+
finishedTimestamp -> finishedTimestamp.isBefore(startTimestamp)));
8368
assertThat(threadNames).hasSize(3);
8469
}
8570

@@ -103,10 +88,6 @@ private Events executeInParallelSuccessfully(int poolSize, Class<?>... testClass
10388
}
10489
}
10590

106-
private Events executeInParallel(int poolSize, Class<?>... testClasses) {
107-
return execute(poolSize, testClasses).allEvents();
108-
}
109-
11091
private static EngineExecutionResults execute(int poolSize, Class<?>... testClass) {
11192
return EngineTestKit.execute(new VintageTestEngine(), request(poolSize, testClass));
11293
}
@@ -116,9 +97,11 @@ private static LauncherDiscoveryRequest request(int poolSize, Class<?>... testCl
11697
.map(DiscoverySelectors::selectClass) //
11798
.toArray(ClassSelector[]::new);
11899

119-
return LauncherDiscoveryRequestBuilder.request().selectors(classSelectors).configurationParameter(
120-
PARALLEL_EXECUTION_ENABLED, String.valueOf(true)).configurationParameter(PARALLEL_POOL_SIZE,
121-
String.valueOf(poolSize)).build();
100+
return LauncherDiscoveryRequestBuilder.request() //
101+
.selectors(classSelectors) //
102+
.configurationParameter(PARALLEL_EXECUTION_ENABLED, String.valueOf(true)) //
103+
.configurationParameter(PARALLEL_POOL_SIZE, String.valueOf(poolSize)) //
104+
.build();
122105
}
123106

124107
}

junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/JUnit4ParallelTestCase.java

Lines changed: 17 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@
1111
package org.junit.vintage.engine.samples.junit4;
1212

1313
import static java.util.concurrent.TimeUnit.MILLISECONDS;
14-
import static org.junit.Assert.fail;
1514

16-
import java.util.HashSet;
1715
import java.util.Set;
16+
import java.util.concurrent.ConcurrentHashMap;
1817
import java.util.concurrent.CountDownLatch;
19-
import java.util.concurrent.atomic.AtomicInteger;
2018

21-
import org.junit.BeforeClass;
2219
import org.junit.Rule;
2320
import org.junit.Test;
2421
import org.junit.experimental.runners.Enclosed;
@@ -29,227 +26,42 @@
2926
@RunWith(Enclosed.class)
3027
public class JUnit4ParallelTestCase {
3128

32-
public static class SuccessfulParallelTestCase {
33-
public static Set<String> threadNames;
34-
static AtomicInteger sharedResource;
35-
static CountDownLatch countDownLatch;
29+
public static class AbstractBlockingTestCase {
3630

37-
@Rule
38-
public final TestWatcher testWatcher = new TestWatcher() {
39-
@Override
40-
protected void starting(Description description) {
41-
super.starting(description);
42-
threadNames.add(Thread.currentThread().getName());
43-
}
44-
};
45-
46-
@BeforeClass
47-
public static void initialize() {
48-
sharedResource = new AtomicInteger();
49-
countDownLatch = new CountDownLatch(3);
50-
threadNames = new HashSet<>();
51-
}
52-
53-
@Test
54-
public void firstTest() throws Exception {
55-
incrementAndBlock(sharedResource, countDownLatch);
56-
}
57-
58-
@Test
59-
public void secondTest() throws Exception {
60-
incrementAndBlock(sharedResource, countDownLatch);
61-
}
62-
63-
@Test
64-
public void thirdTest() throws Exception {
65-
incrementAndBlock(sharedResource, countDownLatch);
66-
}
67-
}
68-
69-
public static class ConcurrentIncrementTestCase {
70-
public static Set<String> threadNames;
71-
static AtomicInteger sharedResource;
72-
static CountDownLatch countDownLatch;
31+
public static final Set<String> threadNames = ConcurrentHashMap.newKeySet();
32+
public static CountDownLatch countDownLatch;
7333

7434
@Rule
7535
public final TestWatcher testWatcher = new TestWatcher() {
7636
@Override
7737
protected void starting(Description description) {
78-
super.starting(description);
79-
threadNames.add(Thread.currentThread().getName());
38+
AbstractBlockingTestCase.threadNames.add(Thread.currentThread().getName());
8039
}
8140
};
8241

83-
@BeforeClass
84-
public static void initialize() {
85-
sharedResource = new AtomicInteger();
86-
countDownLatch = new CountDownLatch(3);
87-
threadNames = new HashSet<>();
88-
}
89-
9042
@Test
91-
public void firstTest() throws Exception {
92-
incrementAndBlock(sharedResource, countDownLatch);
43+
public void test() throws Exception {
44+
countDownAndBlock(countDownLatch);
9345
}
9446

95-
@Test
96-
public void secondTest() throws Exception {
97-
incrementAndBlock(sharedResource, countDownLatch);
47+
@SuppressWarnings("ResultOfMethodCallIgnored")
48+
private static void countDownAndBlock(CountDownLatch countDownLatch) throws InterruptedException {
49+
countDownLatch.countDown();
50+
countDownLatch.await(estimateSimulatedTestDurationInMilliseconds(), MILLISECONDS);
9851
}
9952

100-
@Test
101-
public void thirdTest() throws Exception {
102-
incrementAndBlock(sharedResource, countDownLatch);
53+
private static long estimateSimulatedTestDurationInMilliseconds() {
54+
var runningInCi = Boolean.parseBoolean(System.getenv("CI"));
55+
return runningInCi ? 1000 : 100;
10356
}
10457
}
10558

106-
public static class AtomicOperationParallelTestCase {
107-
public static Set<String> threadNames;
108-
static AtomicInteger sharedResource;
109-
static CountDownLatch countDownLatch;
110-
111-
@Rule
112-
public final TestWatcher testWatcher = new TestWatcher() {
113-
@Override
114-
protected void starting(Description description) {
115-
super.starting(description);
116-
threadNames.add(Thread.currentThread().getName());
117-
}
118-
};
119-
120-
@BeforeClass
121-
public static void initialize() {
122-
sharedResource = new AtomicInteger();
123-
countDownLatch = new CountDownLatch(3);
124-
threadNames = new HashSet<>();
125-
}
126-
127-
@Test
128-
public void firstTest() throws Exception {
129-
incrementAndBlock(sharedResource, countDownLatch);
130-
}
131-
132-
@Test
133-
public void secondTest() throws Exception {
134-
incrementAndBlock(sharedResource, countDownLatch);
135-
}
136-
137-
@Test
138-
public void thirdTest() throws Exception {
139-
incrementAndBlock(sharedResource, countDownLatch);
140-
}
141-
}
142-
143-
public static class FailingParallelTestCase {
144-
public static Set<String> threadNames;
145-
146-
@Rule
147-
public final TestWatcher testWatcher = new TestWatcher() {
148-
@Override
149-
protected void starting(Description description) {
150-
super.starting(description);
151-
threadNames.add(Thread.currentThread().getName());
152-
}
153-
};
154-
155-
@BeforeClass
156-
public static void initialize() {
157-
threadNames = new HashSet<>();
158-
}
159-
160-
@Test
161-
public void firstTest() {
162-
fail("failing test");
163-
}
164-
165-
@Test
166-
public void secondTest() {
167-
fail("failing test");
168-
}
169-
170-
@Test
171-
public void thirdTest() {
172-
fail("failing test");
173-
}
174-
}
175-
176-
public static class ConcurrentFailureTestCase {
177-
public static Set<String> threadNames;
178-
179-
@Rule
180-
public final TestWatcher testWatcher = new TestWatcher() {
181-
@Override
182-
protected void starting(Description description) {
183-
super.starting(description);
184-
threadNames.add(Thread.currentThread().getName());
185-
}
186-
};
187-
188-
@BeforeClass
189-
public static void initialize() {
190-
threadNames = new HashSet<>();
191-
}
192-
193-
@Test
194-
public void firstTest() {
195-
fail("failing test");
196-
}
197-
198-
@Test
199-
public void secondTest() {
200-
fail("failing test");
201-
}
202-
203-
@Test
204-
public void thirdTest() {
205-
fail("failing test");
206-
}
207-
}
208-
209-
public static class ParallelFailingTestCase {
210-
public static Set<String> threadNames;
211-
212-
@Rule
213-
public final TestWatcher testWatcher = new TestWatcher() {
214-
@Override
215-
protected void starting(Description description) {
216-
super.starting(description);
217-
threadNames.add(Thread.currentThread().getName());
218-
}
219-
};
220-
221-
@BeforeClass
222-
public static void initialize() {
223-
threadNames = new HashSet<>();
224-
}
225-
226-
@Test
227-
public void firstTest() {
228-
fail("failing test");
229-
}
230-
231-
@Test
232-
public void secondTest() {
233-
fail("failing test");
234-
}
235-
236-
@Test
237-
public void thirdTest() {
238-
fail("failing test");
239-
}
59+
public static class FirstTestCase extends AbstractBlockingTestCase {
24060
}
24161

242-
@SuppressWarnings("ResultOfMethodCallIgnored")
243-
private static int incrementAndBlock(AtomicInteger sharedResource, CountDownLatch countDownLatch)
244-
throws InterruptedException {
245-
var value = sharedResource.incrementAndGet();
246-
countDownLatch.countDown();
247-
countDownLatch.await(estimateSimulatedTestDurationInMiliseconds(), MILLISECONDS);
248-
return value;
62+
public static class SecondTestCase extends AbstractBlockingTestCase {
24963
}
25064

251-
private static long estimateSimulatedTestDurationInMiliseconds() {
252-
var runningInCi = Boolean.parseBoolean(System.getenv("CI"));
253-
return runningInCi ? 1000 : 100;
65+
public static class ThirdTestCase extends AbstractBlockingTestCase {
25466
}
25567
}

0 commit comments

Comments
 (0)