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
16 changes: 15 additions & 1 deletion documentation/src/docs/asciidoc/user-guide/extensions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,20 @@ Specifically, a custom extension can be registered by supplying its fully qualif
name in a file named `org.junit.jupiter.api.extension.Extension` within the
`/META-INF/services` folder in its enclosing JAR file.

[[automatic-extension-registration-pattern-matching]]
===== Pattern Matching Syntax

Pattern matching syntax is used to automatically detect and register extensions. Here are some examples of pattern matching syntax:

- `*`: includes all extensions.
- `org.junit.*`: includes every extension under the `org.junit` base package and any of its subpackages.
- `*.MyExtension`: includes every extension whose simple class name is exactly `MyExtension`.
- `*System*`: includes every extension whose FQCN contains `System`.
- `*System*, *Dev*`: includes every extension whose FQCN contains `System` or `Dev`.
- `org.example.MyExtension, org.example.TheirExtension`: includes extensions whose FQCN is exactly `org.example.MyExtension` or `org.example.TheirExtension`.

> **Note**: A class that matches both an inclusion and exclusion pattern will be excluded.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should instead just link to the running-tests-config-params-deactivation-pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very skilled at documentation work yet 😅

[[automatic-extension-registration-pattern-matching]]
===== Pattern Matching Syntax

Refer to <<running-tests-config-params-deactivation-pattern>> for details.

Would this change be fine?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't checked the history but I think the main reason this indirection exists in the other places is because we didn't want to break existing links. Since we're introducing new content here, I think we can simplify and link to the target section directly, i.e. without introducing another subsection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this change in 13c1b19


[[extensions-registration-automatic-enabling]]
===== Enabling Automatic Extension Detection

Expand Down Expand Up @@ -368,7 +382,7 @@ following system property.
[[extensions-conditions-deactivation-patterns]]
===== Pattern Matching Syntax

Refer to <<running-tests-config-params-deactivation-pattern>> for details.
Pattern matching syntax is used to automatically detect and register extensions. For more details, refer to the <<automatic-extension-registration-pattern-matching,Pattern Matching Syntax>> section.

[[extensions-test-instance-pre-construct-callback]]
=== Test Instance Pre-construct Callback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public final class Constants {
* {@code org.example.TheirExtension}.
* </ul>
*
* <p>Note: A class that matches both an inclusion and exclusion pattern will be excluded.
*
* @see JupiterConfiguration#EXTENSIONS_AUTODETECTION_INCLUDE_PROPERTY_NAME
*/
public static final String EXTENSIONS_AUTODETECTION_INCLUDE_PROPERTY_NAME = JupiterConfiguration.EXTENSIONS_AUTODETECTION_INCLUDE_PROPERTY_NAME;
Expand Down Expand Up @@ -115,6 +117,8 @@ public final class Constants {
* {@code org.example.TheirExtension}.
* </ul>
*
* <p>Note: A class that matches both an inclusion and exclusion pattern will be excluded.
*
* @see JupiterConfiguration#EXTENSIONS_AUTODETECTION_EXCLUDE_PROPERTY_NAME
*/
public static final String EXTENSIONS_AUTODETECTION_EXCLUDE_PROPERTY_NAME = JupiterConfiguration.EXTENSIONS_AUTODETECTION_EXCLUDE_PROPERTY_NAME;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public CachingJupiterConfiguration(JupiterConfiguration delegate) {
}

@Override
public Predicate<Class<? extends Extension>> createExtensionFilterByPatterns() {
return delegate.createExtensionFilterByPatterns();
public Predicate<Class<? extends Extension>> getFilterForAutoDetectedExtensions() {
return delegate.getFilterForAutoDetectedExtensions();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public DefaultJupiterConfiguration(ConfigurationParameters configurationParamete
}

@Override
public Predicate<Class<? extends Extension>> createExtensionFilterByPatterns() {
public Predicate<Class<? extends Extension>> getFilterForAutoDetectedExtensions() {
Predicate<String> predicate = ClassNamePatternFilterUtils.includeMatchingClassNames(
getExtensionAutodetectionIncludePattern().orElse(ClassNamePatternFilterUtils.ALL_PATTERN)) //
.and(ClassNamePatternFilterUtils.excludeMatchingClassNames(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ 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;

Predicate<Class<? extends Extension>> createExtensionFilterByPatterns();
Predicate<Class<? extends Extension>> getFilterForAutoDetectedExtensions();

Optional<String> getRawConfigurationParameter(String key);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apiguardian.api.API;
Expand Down Expand Up @@ -97,12 +98,34 @@ public static MutableExtensionRegistry createRegistryWithDefaultExtensions(Jupit

private static void registerAutoDetectedExtensions(MutableExtensionRegistry extensionRegistry,
JupiterConfiguration configuration) {
Predicate<Class<? extends Extension>> filter = configuration.createExtensionFilterByPatterns();
Predicate<Class<? extends Extension>> filter = configuration.getFilterForAutoDetectedExtensions();

ServiceLoader<Extension> serviceLoader = ServiceLoader.load(Extension.class,
ClassLoaderUtils.getDefaultClassLoader());
ServiceLoaderUtils.filter(serviceLoader, filter) //
.forEach(extensionRegistry::registerAutoDetectedExtension);

logExcludedExtensions(serviceLoader, filter);
}

private static void logExcludedExtensions(ServiceLoader<Extension> serviceLoader,
Predicate<Class<? extends Extension>> filter) {
List<Class<? extends Extension>> excludeExtensions = new ArrayList<>();
serviceLoader.forEach(extension -> {
if (!filter.test(extension.getClass())) {
excludeExtensions.add(extension.getClass());
}
});

if (!excludeExtensions.isEmpty()) {
// @formatter:off
List<String> excludeExtensionNames = excludeExtensions
.stream()
.map(Class::getName)
.collect(Collectors.toList());
// @formatter:on
logger.config(() -> String.format("Excluded auto-detected extensions: %s", excludeExtensionNames));
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void newRegistryWithoutParentHasDefaultExtensions() {
void newRegistryWithoutParentHasDefaultExtensionsPlusAutodetectedExtensionsLoadedViaServiceLoader() {

when(configuration.isExtensionAutoDetectionEnabled()).thenReturn(true);
when(configuration.createExtensionFilterByPatterns()).thenReturn(__ -> true);
when(configuration.getFilterForAutoDetectedExtensions()).thenReturn(__ -> true);
registry = createRegistryWithDefaultExtensions(configuration);

List<Extension> extensions = registry.getExtensions(Extension.class);
Expand Down