forked from junit-team/junit5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve resource container selectors
As a follow up for junit-team#3630 and junit-team#3705 this adds a `addResourceContainerSelectorResolver()` method to `EngineDiscoveryRequestResolver.Builder` analogous to `addClassContainerSelectorResolver()`. Points of note: * As classpath resources can be selected from packages, the package filter should also be applied. To make this possible the base path of a resource is rewritten to a package name prior to being filtered. * The `ClasspathResourceSelector` now has a `getClasspathResource` method. This method will lazily try to load the resource if not was not already provided when discovering resources in a container. * `selectClasspathResource(Resource)` was added to short circuit the need to resolve resources twice. And to make it possible to use this method as part of the public API, `ReflectionSupport.tryToLoadResource` was also added.
- Loading branch information
1 parent
704e584
commit 9cbc960
Showing
9 changed files
with
398 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
...n/java/org/junit/platform/engine/support/discovery/ResourceContainerSelectorResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* 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.engine.support.discovery; | ||
|
||
import static java.util.stream.Collectors.toSet; | ||
import static org.junit.platform.commons.support.ReflectionSupport.findAllResourcesInClasspathRoot; | ||
import static org.junit.platform.commons.support.ReflectionSupport.findAllResourcesInPackage; | ||
import static org.junit.platform.commons.util.ReflectionUtils.findAllResourcesInModule; | ||
import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.selectors; | ||
import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; | ||
|
||
import java.util.List; | ||
import java.util.function.Predicate; | ||
|
||
import org.junit.platform.commons.support.Resource; | ||
import org.junit.platform.engine.discovery.ClasspathRootSelector; | ||
import org.junit.platform.engine.discovery.DiscoverySelectors; | ||
import org.junit.platform.engine.discovery.ModuleSelector; | ||
import org.junit.platform.engine.discovery.PackageSelector; | ||
|
||
/** | ||
* @since 1.11 | ||
*/ | ||
class ResourceContainerSelectorResolver implements SelectorResolver { | ||
private static final char CLASSPATH_RESOURCE_PATH_SEPARATOR = '/'; | ||
private static final char PACKAGE_SEPARATOR_CHAR = '.'; | ||
public static final String DEFAULT_PACKAGE_NAME = ""; | ||
private final Predicate<Resource> resourceFilter; | ||
private final Predicate<String> resourcePackageFilter; | ||
|
||
ResourceContainerSelectorResolver(Predicate<Resource> resourceFilter, Predicate<String> resourcePackageFilter) { | ||
this.resourceFilter = resourceFilter; | ||
this.resourcePackageFilter = adaptPackageFilter(resourcePackageFilter); | ||
} | ||
|
||
/** | ||
* A package filter is written to test {@code .} separated package names. | ||
* Resources however have {@code /} separated paths. By rewriting the path | ||
* of the resource into a package name, we can make the package filter work. | ||
*/ | ||
private static Predicate<String> adaptPackageFilter(Predicate<String> packageFilter) { | ||
return classpathResourceName -> packageFilter.test(packageName(classpathResourceName)); | ||
} | ||
|
||
private static String packageName(String classpathResourceName) { | ||
int lastIndexOf = classpathResourceName.lastIndexOf(CLASSPATH_RESOURCE_PATH_SEPARATOR); | ||
if (lastIndexOf < 0) { | ||
return DEFAULT_PACKAGE_NAME; | ||
} | ||
// classpath resource names do not start with / | ||
String resourcePackagePath = classpathResourceName.substring(0, lastIndexOf); | ||
return resourcePackagePath.replace(CLASSPATH_RESOURCE_PATH_SEPARATOR, PACKAGE_SEPARATOR_CHAR); | ||
} | ||
|
||
@Override | ||
public Resolution resolve(ClasspathRootSelector selector, Context context) { | ||
return resourceSelectors( | ||
findAllResourcesInClasspathRoot(selector.getClasspathRoot(), resourceFilter, resourcePackageFilter)); | ||
} | ||
|
||
@Override | ||
public Resolution resolve(ModuleSelector selector, Context context) { | ||
return resourceSelectors( | ||
findAllResourcesInModule(selector.getModuleName(), resourceFilter, resourcePackageFilter)); | ||
} | ||
|
||
@Override | ||
public Resolution resolve(PackageSelector selector, Context context) { | ||
return resourceSelectors( | ||
findAllResourcesInPackage(selector.getPackageName(), resourceFilter, resourcePackageFilter)); | ||
} | ||
|
||
private Resolution resourceSelectors(List<Resource> resources) { | ||
if (resources.isEmpty()) { | ||
return unresolved(); | ||
} | ||
return selectors(resources.stream().map(DiscoverySelectors::selectClasspathResource).collect(toSet())); | ||
} | ||
|
||
} |
Oops, something went wrong.