Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cfb6845
Enable specific global extension in JUnit 5
YongGoose Nov 12, 2024
07a6ae3
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/ex…
YongGoose Nov 14, 2024
4a896f1
Add Java 9+ variant for optimized ServiceLoader filtering
YongGoose Nov 14, 2024
7c58f66
Merge branch 'main' into feature/enable-specific-global-extensions-in…
YongGoose Nov 16, 2024
09dca93
Remove final keyword
YongGoose Nov 18, 2024
355e113
Merge branch 'main' into feature/enable-specific-global-extensions-in…
YongGoose Nov 18, 2024
2568ffe
Avoid instantiating deactivated TestExecutionListeners
marcphilipp Nov 19, 2024
d5a3511
Pass ServiceLoader to Utils to avoid failing its caller check
marcphilipp Nov 19, 2024
a599008
Merge pull request #1 from junit-team/marc/avoid-deactivated-test-exe…
YongGoose Nov 19, 2024
8b2f41e
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/ex…
YongGoose Nov 19, 2024
eb32053
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/ex…
YongGoose Nov 19, 2024
1597992
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/ex…
YongGoose Nov 19, 2024
eb1b5b3
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/ex…
YongGoose Nov 19, 2024
f86c1d6
Add constants and javadoc for supported syntax
YongGoose Nov 19, 2024
02c91b5
move code to JupiterConfiguration
YongGoose Nov 19, 2024
3c95ac9
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/co…
YongGoose Nov 27, 2024
624760b
Rename method
YongGoose Nov 27, 2024
6c5d6c3
Add javadoc
YongGoose Nov 27, 2024
13645f0
Update user-guide
YongGoose Nov 27, 2024
9daa88a
Merge branch 'main' into feature/enable-specific-global-extensions-in…
YongGoose Nov 29, 2024
f870747
Log excluded classes once
YongGoose Nov 30, 2024
671e387
Update junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/ex…
YongGoose Dec 5, 2024
87ac022
Merge branch 'main' into feature/enable-specific-global-extensions-in…
YongGoose Dec 5, 2024
a190de6
Apply spotless
YongGoose Dec 5, 2024
13c1b19
Update user-guide
YongGoose Dec 5, 2024
6e5b161
Document new configuration parameters
marcphilipp Dec 6, 2024
ec13b6d
Add integration test
YongGoose Dec 14, 2024
ff30825
Merge remote-tracking branch 'origin/feature/enable-specific-global-e…
YongGoose Dec 14, 2024
4b3c670
Avoid 2nd loop and loading all extensions
marcphilipp Dec 16, 2024
6279713
Polish tests
marcphilipp Dec 16, 2024
93f0e2f
Improve readability
marcphilipp Dec 16, 2024
f92b14d
Return "constant" predicates for default case
marcphilipp Dec 16, 2024
fbefdc9
Remove orphaned anchor
marcphilipp Dec 16, 2024
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 @@ -46,6 +46,16 @@ public CachingJupiterConfiguration(JupiterConfiguration delegate) {
this.delegate = delegate;
}

@Override
public Optional<String> getExtensionAutodetectionIncludePattern() {
return delegate.getExtensionAutodetectionIncludePattern();
}

@Override
public Optional<String> getExtensionAutodetectionExcludePattern() {
return delegate.getExtensionAutodetectionExcludePattern();
}

@Override
public Optional<String> getRawConfigurationParameter(String key) {
return delegate.getRawConfigurationParameter(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ public DefaultJupiterConfiguration(ConfigurationParameters configurationParamete
"ConfigurationParameters must not be null");
}

@Override
public Optional<String> getExtensionAutodetectionIncludePattern() {
return configurationParameters.get(EXTENSIONS_AUTODETECTION_INCLUDE_PROPERTY_NAME);
}

@Override
public Optional<String> getExtensionAutodetectionExcludePattern() {
return configurationParameters.get(EXTENSIONS_AUTODETECTION_EXCLUDE_PROPERTY_NAME);
}

@Override
public Optional<String> getRawConfigurationParameter(String key) {
return configurationParameters.get(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
@API(status = INTERNAL, since = "5.4")
public interface JupiterConfiguration {

String EXTENSIONS_AUTODETECTION_INCLUDE_PROPERTY_NAME = "junit.jupiter.extensions.autodetection.include";
String EXTENSIONS_AUTODETECTION_EXCLUDE_PROPERTY_NAME = "junit.jupiter.extensions.autodetection.exclude";
String DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME = "junit.jupiter.conditions.deactivate";
String PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME = "junit.jupiter.execution.parallel.enabled";
String DEFAULT_EXECUTION_MODE_PROPERTY_NAME = Execution.DEFAULT_EXECUTION_MODE_PROPERTY_NAME;
Expand All @@ -48,6 +50,10 @@ public interface JupiterConfiguration {
String DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME = ClassOrderer.DEFAULT_ORDER_PROPERTY_NAME;;
String DEFAULT_TEST_INSTANTIATION_EXTENSION_CONTEXT_SCOPE_PROPERTY_NAME = ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME;

Optional<String> getExtensionAutodetectionIncludePattern();

Optional<String> getExtensionAutodetectionExcludePattern();

Optional<String> getRawConfigurationParameter(String key);

<T> Optional<T> getRawConfigurationParameter(String key, Function<String, T> transformer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.apiguardian.api.API;
Expand All @@ -37,7 +38,9 @@
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.support.ReflectionSupport;
import org.junit.platform.commons.util.ClassLoaderUtils;
import org.junit.platform.commons.util.ClassNamePatternFilterUtils;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ServiceLoaderUtils;

/**
* Default, mutable implementation of {@link ExtensionRegistry}.
Expand Down Expand Up @@ -83,7 +86,7 @@ public static MutableExtensionRegistry createRegistryWithDefaultExtensions(Jupit
extensionRegistry.registerDefaultExtension(new TempDirectory(configuration));

if (configuration.isExtensionAutoDetectionEnabled()) {
registerAutoDetectedExtensions(extensionRegistry);
registerAutoDetectedExtensions(extensionRegistry, configuration);
}

if (configuration.isThreadDumpOnTimeoutEnabled()) {
Expand All @@ -93,11 +96,25 @@ public static MutableExtensionRegistry createRegistryWithDefaultExtensions(Jupit
return extensionRegistry;
}

private static void registerAutoDetectedExtensions(MutableExtensionRegistry extensionRegistry) {
ServiceLoader.load(Extension.class, ClassLoaderUtils.getDefaultClassLoader())//
private static void registerAutoDetectedExtensions(MutableExtensionRegistry extensionRegistry,
JupiterConfiguration configuration) {
Predicate<? super Class<? extends Extension>> filter = createExtensionFilterByPatterns(
configuration.getExtensionAutodetectionIncludePattern().orElse("*"),
configuration.getExtensionAutodetectionExcludePattern().orElse(""));

ServiceLoaderUtils.load(Extension.class, filter, ClassLoaderUtils.getDefaultClassLoader()) //
.forEach(extensionRegistry::registerAutoDetectedExtension);
}

private static Predicate<? super Class<? extends Extension>> createExtensionFilterByPatterns(String include,
String exclude) {
return clazz -> {
String className = clazz.getName();
return ClassNamePatternFilterUtils.includeMatchingClassNames(include).test(className) //
&& ClassNamePatternFilterUtils.excludeMatchingClassNames(exclude).test(className);
};
}

/**
* Factory for creating and populating a new registry from a list of
* extension types and a parent registry.
Expand Down
1 change: 1 addition & 0 deletions junit-platform-commons/junit-platform-commons.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ tasks.jar {
tasks.codeCoverageClassesJar {
exclude("org/junit/platform/commons/util/ModuleUtils.class")
exclude("org/junit/platform/commons/util/PackageNameUtils.class")
exclude("org/junit/platform/commons/util/ServiceLoaderUtils.class")
}

eclipse {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;

import java.util.ServiceLoader;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.apiguardian.api.API;

/**
* Collection of utilities for working with {@link ServiceLoader}.
*
* <h2>DISCLAIMER</h2>
*
* <p>These utilities are intended solely for usage within the JUnit framework
* itself. <strong>Any usage by external parties is not supported.</strong>
* Use at your own risk!
*
* @since 5.11
*/
@API(status = API.Status.INTERNAL, since = "5.11")
public class ServiceLoaderUtils {

private ServiceLoaderUtils() {
/* no-op */
}

/**
* Loads services of the given type using the specified class loader and filters them using the provided predicate.
*
* @param <T> the type of the service
* @param service the class of the service to be loaded
* @param providerPredicate the predicate to filter the loaded services
* @param loader the class loader to be used to load the services
* @return a stream of loaded services that match the predicate
*/
public static <T> Stream<T> load(Class<T> service, Predicate<? super Class<? extends T>> providerPredicate,
ClassLoader loader) {
return StreamSupport.stream(ServiceLoader.load(service, loader).spliterator(), false).filter(it -> {
@SuppressWarnings("unchecked")
Class<? extends T> type = (Class<? extends T>) it.getClass();
return providerPredicate.test(type);
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;

import java.util.ServiceLoader;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

/**
* Collection of utilities for working with {@link ServiceLoader}.
*
* <h2>DISCLAIMER</h2>
*
* <p>These utilities are intended solely for usage within the JUnit framework
* itself. <strong>Any usage by external parties is not supported.</strong>
* Use at your own risk!
*
* @since 5.11
*/
@API(status = Status.INTERNAL, since = "5.11")
public class ServiceLoaderUtils {

private ServiceLoaderUtils() {
/* no-op */
}

/**
* Loads services of the given type using the specified class loader and filters them using the provided predicate.
*
* @param <T> the type of the service
* @param service the class of the service to be loaded
* @param providerPredicate the predicate to filter the loaded services
* @param loader the class loader to be used to load the services
* @return a stream of loaded services that match the predicate
*/
public static <T> Stream<T> load(Class<T> service, Predicate<? super Class<? extends T>> providerPredicate,
ClassLoader loader) {
// @formatter:off
return ServiceLoader.load(service, loader)
.stream()
.filter(provider -> providerPredicate.test(provider.type()))
.map(ServiceLoader.Provider::get);
// @formatter:on
}

}