Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,22 +164,18 @@ concurrently. You can configure which implementation of `HierarchicalTestExecuto
is used be setting the `junit.jupiter.execution.parallel.config.executor-service`
configuration parameter to one of the following options:

`fork_join_pool` (default)::
`worker_thread_pool` (default)::
Use an executor service that is backed by a `ThreadPoolExecutor`. The
executor service tries to maintain the desired parallelism but does
not compensate for test or production code using blocking APIs in the JDK.

`fork_join_pool`::
Use an executor service that is backed by a `ForkJoinPool` from the JDK. This will cause
tests to be executed in a `ForkJoinWorkerThread`. In some cases, usages of
`ForkJoinPool` in test or production code or calls to blocking JDK APIs may cause the
number of concurrently executing tests to increase. To avoid this situation, please use
`worker_thread_pool`.

`worker_thread_pool` (experimental)::
Use an executor service that is backed by a regular thread pool and does not create
additional threads if test or production code uses `ForkJoinPool` or calls a blocking
API in the JDK.

WARNING: Using `worker_thread_pool` is currently an _experimental_ feature. You're invited
to give it a try and provide feedback to the JUnit team so they can improve and eventually
xref:api-evolution.adoc[promote] this feature.

[[config-strategies]]
=== Strategies

Expand Down Expand Up @@ -241,7 +237,7 @@ xref:running-tests/configuration-parameters.adoc[] for details on how to set suc

`junit.jupiter.execution.parallel.config.executor-service=fork_join_pool|worker_thread_pool`::
Type of `HierarchicalTestExecutorService` to use for parallel execution (defaults to
`fork_join_pool`).
`worker_thread_pool`).

`junit.jupiter.execution.parallel.config.strategy=dynamic|fixed|custom`::
Execution strategy for desired parallelism, maximum pool size, etc. (defaults to `dynamic`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ repository on GitHub.
xref:advanced-topics/configuration-parameter-documentation.adoc[Documenting Configuration
Parameters] for more information.
* Platform configuration parameters are documented in `META-INF/junit-platform-configuration-metadata.json`
* Test engines using the `ParallelHierarchicalTestExecutorServiceFactory` now use the
`WORKER_THREAD_POOL` executor service by default.

[[v6.2.0-M1-junit-jupiter]]
=== JUnit Jupiter
Expand Down Expand Up @@ -81,6 +83,8 @@ repository on GitHub.
* The `assertTimeout`, `assertTimeoutPreemptively` and methods annotated with `@Timeout`
now measure the execution time with sub-millisecond precision.
* Jupiter configuration parameters are documented in `META-INF/junit-platform-configuration-metadata.json`
* The `junit.jupiter.execution.parallel.config.executor-service` configuration parameter
now defaults to `WORKER_THREAD_POOL` when parallel execution is enabled.

[[v6.2.0-M1-junit-vintage]]
=== JUnit Vintage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@
import static org.junit.jupiter.api.Constants.EXTENSIONS_AUTODETECTION_INCLUDE_PROPERTY_NAME;
import static org.junit.jupiter.api.Constants.EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME;
import static org.junit.jupiter.api.Constants.INCLUDE_ALL_EXTENSIONS_PATTERN;
import static org.junit.jupiter.api.Constants.PARALLEL_CONFIG_EXECUTOR_SERVICE_PROPERTY_NAME;
import static org.junit.jupiter.api.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME;
import static org.junit.jupiter.api.Defaults.CLOSING_STORED_AUTO_CLOSEABLE_ENABLED_DEFAULT;
import static org.junit.jupiter.api.Defaults.EXTENSIONS_AUTODETECTION_ENABLED_DEFAULT;
import static org.junit.jupiter.api.Defaults.PARALLEL_EXECUTION_ENABLED_DEFAULT;
import static org.junit.jupiter.engine.config.FilteringConfigurationParameterConverter.exclude;
import static org.junit.platform.engine.support.hierarchical.ParallelHierarchicalTestExecutorServiceFactory.ParallelExecutorServiceType.FORK_JOIN_POOL;
import static org.junit.platform.engine.support.hierarchical.ParallelHierarchicalTestExecutorServiceFactory.ParallelExecutorServiceType.WORKER_THREAD_POOL;

import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -129,17 +126,6 @@ private void validateConfigurationParameters(DiscoveryIssueReporter issueReporte
Please remove it from your configuration.""".formatted(key));
issueReporter.reportIssue(warning);
}));
if (isParallelExecutionEnabled()
&& configurationParameters.get(PARALLEL_CONFIG_EXECUTOR_SERVICE_PROPERTY_NAME).isEmpty()) {
var info = DiscoveryIssue.create(Severity.INFO,
"Parallel test execution is enabled but the default ForkJoinPool-based executor service will be used. "
+ "Please give the new implementation based on a regular thread pool a try by setting the '"
+ PARALLEL_CONFIG_EXECUTOR_SERVICE_PROPERTY_NAME + "' configuration parameter to '"
+ WORKER_THREAD_POOL + "' and report any issues to the JUnit team. "
+ "Alternatively, set the configuration parameter to '" + FORK_JOIN_POOL
+ "' to hide this message and keep using the original implementation.");
issueReporter.reportIssue(info);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

package org.junit.platform.engine.support.hierarchical;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;
import static org.apiguardian.api.API.Status.MAINTAINED;

import java.util.Locale;
Expand All @@ -36,7 +35,7 @@ public final class ParallelHierarchicalTestExecutorServiceFactory {
* Default value for {@value #EXECUTOR_SERVICE_PROPERTY_NAME} is {@value}.
*/
@API(status = MAINTAINED, since = "6.2")
public static final String EXECUTOR_SERVICE_DEFAULT = "FORK_JOIN_POOL";
public static final String EXECUTOR_SERVICE_DEFAULT = "WORKER_THREAD_POOL";

/**
* Property name used to determine the desired
Expand Down Expand Up @@ -117,7 +116,7 @@ public enum ParallelExecutorServiceType {
* Indicates that {@link WorkerThreadPoolHierarchicalTestExecutorService}
* should be used.
*/
@API(status = EXPERIMENTAL, since = "6.1")
@API(status = MAINTAINED, since = "6.2")
WORKER_THREAD_POOL;

private static ParallelExecutorServiceType parse(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
import static org.apiguardian.api.API.Status.MAINTAINED;
import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException;
import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ_WRITE;
import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.SAME_THREAD;
Expand Down Expand Up @@ -67,7 +67,7 @@
* @see ParallelExecutorServiceType#WORKER_THREAD_POOL
* @see DefaultParallelExecutionConfigurationStrategy
*/
@API(status = EXPERIMENTAL, since = "6.1")
@API(status = MAINTAINED, since = "6.2")
public final class WorkerThreadPoolHierarchicalTestExecutorService implements HierarchicalTestExecutorService {

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.platform.engine.ConfigurationParameters;
import org.junit.platform.engine.DiscoveryIssue;
import org.junit.platform.engine.DiscoveryIssue.Severity;
import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter;
import org.junit.platform.engine.support.hierarchical.ParallelHierarchicalTestExecutorServiceFactory.ParallelExecutorServiceType;
import org.junit.platform.launcher.core.ConfigurationParametersFactoryForTests;
Expand Down Expand Up @@ -187,22 +186,6 @@ void doesNotReportAnyIssuesIfParallelExecutionIsEnabledAndConfigurationParameter
assertThat(issues).isEmpty();
}

@Test
void asksUsersToTryWorkerThreadPoolHierarchicalExecutorServiceIfParallelExecutionIsEnabled() {
var parameters = Map.of(Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, true);
List<DiscoveryIssue> issues = new ArrayList<>();

new DefaultJupiterConfiguration(configurationParameters(parameters), dummyOutputDirectoryCreator(),
DiscoveryIssueReporter.collecting(issues)).getDefaultTestInstanceLifecycle();

assertThat(issues).containsExactly(DiscoveryIssue.create(Severity.INFO, """
Parallel test execution is enabled but the default ForkJoinPool-based executor service will be used. \
Please give the new implementation based on a regular thread pool a try by setting the \
'junit.jupiter.execution.parallel.config.executor-service' configuration parameter to \
'WORKER_THREAD_POOL' and report any issues to the JUnit team. Alternatively, set the configuration \
parameter to 'FORK_JOIN_POOL' to hide this message and keep using the original implementation."""));
}

private void assertDefaultConfigParam(@Nullable String configValue, Lifecycle expected) {
var lifecycle = getDefaultTestInstanceLifecycleConfigParam(configValue);
assertThat(lifecycle).isEqualTo(expected);
Expand Down
Loading