import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.RepeatedTest; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.stream.IntStream; final class ForkJoinPoolTest { // Needs to be executed with the following VM options to reproduce the issues: // -Djunit.jupiter.execution.parallel.enabled=true // -Djunit.jupiter.execution.parallel.mode.default=concurrent // -Djunit.jupiter.execution.parallel.mode.classes.default=concurrent private static final ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); @RepeatedTest(1000) void throwRejectedExecutionException() throws Exception { for (int i = 0; i < 10; i++) { ForkJoinPool.commonPool() .submit(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { throw new IllegalStateException(e); } }) .get(); } } @RepeatedTest(1000) void recursiveCalls() { Assertions.assertNull(THREAD_LOCAL.get()); UUID uuid = UUID.randomUUID(); THREAD_LOCAL.set(uuid); try { int sum = IntStream.range(0, 1_000_000) .parallel() .peek(j -> { try { ForkJoinPool.commonPool() .submit(() -> {}) .get(); } catch (InterruptedException | ExecutionException e) { throw new IllegalStateException(e); } }) .sum(); Assertions.assertNotEquals(0, sum); } finally { Assertions.assertEquals(uuid, THREAD_LOCAL.get()); THREAD_LOCAL.remove(); } } }