Skip to content

Commit ba61097

Browse files
committed
Add Module instance support in ModuleSelector
Closes #4852
1 parent cee1471 commit ba61097

File tree

12 files changed

+188
-9
lines changed

12 files changed

+188
-9
lines changed

junit-platform-commons/src/main/java/org/junit/platform/commons/support/ReflectionSupport.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,31 @@ public static List<Class<?>> findAllClassesInModule(String moduleName, Predicate
391391
return ReflectionUtils.findAllClassesInModule(moduleName, classFilter, classNameFilter);
392392
}
393393

394+
/**
395+
* Find all {@linkplain Class classes} in the supplied {@code module}
396+
* that match the specified {@code classFilter} and {@code classNameFilter}
397+
* predicates.
398+
*
399+
* <p>The module-path scanning algorithm searches recursively in all
400+
* packages contained in the module.
401+
*
402+
* @param module the module to scan; never {@code null} or <em>empty</em>
403+
* @param classFilter the class type filter; never {@code null}
404+
* @param classNameFilter the class name filter; never {@code null}
405+
* @return an immutable list of all such classes found; never {@code null}
406+
* but potentially empty
407+
* @since 6.1
408+
* @see #findAllClassesInClasspathRoot(URI, Predicate, Predicate)
409+
* @see #findAllClassesInPackage(String, Predicate, Predicate)
410+
* @see ResourceSupport#findAllResourcesInModule(String, ResourceFilter)
411+
*/
412+
@API(status = MAINTAINED, since = "6.1")
413+
public static List<Class<?>> findAllClassesInModule(Module module, Predicate<Class<?>> classFilter,
414+
Predicate<String> classNameFilter) {
415+
416+
return ReflectionUtils.findAllClassesInModule(module, classFilter, classNameFilter);
417+
}
418+
394419
/**
395420
* Find all {@linkplain Resource resources} in the supplied {@code moduleName}
396421
* that match the specified {@code resourceFilter} predicate.

junit-platform-commons/src/main/java/org/junit/platform/commons/support/ResourceSupport.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,26 @@ public static List<Resource> findAllResourcesInModule(String moduleName, Resourc
193193
return ReflectionUtils.findAllResourcesInModule(moduleName, resourceFilter);
194194
}
195195

196+
/**
197+
* Find all {@linkplain Resource resources} in the supplied {@code moduleName}
198+
* that match the specified {@code resourceFilter}.
199+
*
200+
* <p>The module-path scanning algorithm searches recursively in all
201+
* packages contained in the module.
202+
*
203+
* @param module the module to scan; never {@code null} or <em>empty</em>
204+
* @param resourceFilter the resource type filter; never {@code null}
205+
* @return an immutable list of all such resources found; never {@code null}
206+
* but potentially empty
207+
* @see #findAllResourcesInClasspathRoot(URI, ResourceFilter)
208+
* @see #findAllResourcesInPackage(String, ResourceFilter)
209+
* @see ReflectionSupport#findAllClassesInModule(String, Predicate, Predicate)
210+
*/
211+
@API(status = MAINTAINED, since = "6.1")
212+
public static List<Resource> findAllResourcesInModule(Module module, ResourceFilter resourceFilter) {
213+
return ReflectionUtils.findAllResourcesInModule(module, resourceFilter);
214+
}
215+
196216
/**
197217
* Find all {@linkplain Resource resources} in the supplied {@code moduleName}
198218
* that match the specified {@code resourceFilter}.

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,27 @@ public static List<Class<?>> findAllClassesInModule(String moduleName, ClassFilt
109109
return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader());
110110
}
111111

112+
/**
113+
* Find all {@linkplain Class classes} for the given module.
114+
*
115+
* @param module the module to scan; never {@code null} or <em>empty</em>
116+
* @param filter the class filter to apply; never {@code null}
117+
* @return an immutable list of all such classes found; never {@code null}
118+
* but potentially empty
119+
* @since 6.1
120+
*/
121+
@API(status = INTERNAL, since = "6.1")
122+
public static List<Class<?>> findAllClassesInModule(Module module, ClassFilter filter) {
123+
Preconditions.notNull(module, "Module must not be null");
124+
Preconditions.condition(module.isNamed(), "Module must not be unnamed");
125+
Preconditions.notNull(filter, "Class filter must not be null");
126+
127+
String name = module.getName();
128+
logger.debug(() -> "Looking for classes in module: " + name);
129+
var reference = module.getLayer().configuration().findModule(name).orElseThrow().reference();
130+
return scan(Set.of(reference), filter, module.getClassLoader());
131+
}
132+
112133
/**
113134
* Find all {@linkplain Resource resources} for the given module name.
114135
*
@@ -124,7 +145,7 @@ public static List<Resource> findAllResourcesInModule(String moduleName, Resourc
124145
Preconditions.notBlank(moduleName, "Module name must not be null or empty");
125146
Preconditions.notNull(filter, "Resource filter must not be null");
126147

127-
logger.debug(() -> "Looking for classes in module: " + moduleName);
148+
logger.debug(() -> "Looking for resources in module: " + moduleName);
128149
// @formatter:off
129150
Set<ModuleReference> moduleReferences = streamResolvedModules(isEqual(moduleName))
130151
.map(ResolvedModule::reference)
@@ -133,6 +154,27 @@ public static List<Resource> findAllResourcesInModule(String moduleName, Resourc
133154
return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader());
134155
}
135156

157+
/**
158+
* Find all {@linkplain Resource resources} for the given module.
159+
*
160+
* @param module the module to scan; never {@code null} or <em>empty</em>
161+
* @param filter the class filter to apply; never {@code null}
162+
* @return an immutable list of all such resources found; never {@code null}
163+
* but potentially empty
164+
* @since 6.1
165+
*/
166+
@API(status = INTERNAL, since = "6.1")
167+
public static List<Resource> findAllResourcesInModule(Module module, ResourceFilter filter) {
168+
Preconditions.notNull(module, "Module must not be null");
169+
Preconditions.condition(module.isNamed(), "Module must not be unnamed");
170+
Preconditions.notNull(filter, "Resource filter must not be null");
171+
172+
String name = module.getName();
173+
logger.debug(() -> "Looking for resources in module: " + name);
174+
var reference = module.getLayer().configuration().findModule(name).orElseThrow().reference();
175+
return scan(Set.of(reference), filter, module.getClassLoader());
176+
}
177+
136178
/**
137179
* Stream resolved modules from current (or boot) module layer.
138180
*/
@@ -175,18 +217,18 @@ private static List<Class<?>> scan(Set<ModuleReference> references, ClassFilter
175217
}
176218

177219
/**
178-
* Scan for classes using the supplied set of module references, class
220+
* Scan for resources using the supplied set of module references, class
179221
* filter, and loader.
180222
*/
181223
private static List<Resource> scan(Set<ModuleReference> references, ResourceFilter filter, ClassLoader loader) {
182224
logger.debug(() -> "Scanning " + references.size() + " module references: " + references);
183225
ModuleReferenceResourceScanner scanner = new ModuleReferenceResourceScanner(filter, loader);
184-
List<Resource> classes = new ArrayList<>();
226+
List<Resource> resources = new ArrayList<>();
185227
for (ModuleReference reference : references) {
186-
classes.addAll(scanner.scan(reference));
228+
resources.addAll(scanner.scan(reference));
187229
}
188-
logger.debug(() -> "Found " + classes.size() + " classes: " + classes);
189-
return List.copyOf(classes);
230+
logger.debug(() -> "Found " + resources.size() + " resources: " + resources);
231+
return List.copyOf(resources);
190232
}
191233

192234
/**

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ReflectionUtils.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,16 @@ public static List<Class<?>> findAllClassesInModule(String moduleName, Predicate
10611061
return findAllClassesInModule(moduleName, ClassFilter.of(classNameFilter, classFilter));
10621062
}
10631063

1064+
/**
1065+
* @since 6.1
1066+
* @see org.junit.platform.commons.support.ReflectionSupport#findAllClassesInModule(Module, Predicate, Predicate)
1067+
*/
1068+
public static List<Class<?>> findAllClassesInModule(Module module, Predicate<Class<?>> classFilter,
1069+
Predicate<String> classNameFilter) {
1070+
// unmodifiable since returned by public, non-internal method(s)
1071+
return findAllClassesInModule(module, ClassFilter.of(classNameFilter, classFilter));
1072+
}
1073+
10641074
/**
10651075
* @since 1.10
10661076
* @see org.junit.platform.commons.support.ReflectionSupport#streamAllClassesInModule(String, Predicate, Predicate)
@@ -1077,13 +1087,27 @@ public static List<Class<?>> findAllClassesInModule(String moduleName, ClassFilt
10771087
return List.copyOf(ModuleUtils.findAllClassesInModule(moduleName, classFilter));
10781088
}
10791089

1090+
/**
1091+
* @since 6.1
1092+
*/
1093+
public static List<Class<?>> findAllClassesInModule(Module module, ClassFilter classFilter) {
1094+
return List.copyOf(ModuleUtils.findAllClassesInModule(module, classFilter));
1095+
}
1096+
10801097
/**
10811098
* @since 1.11
10821099
*/
10831100
public static List<Resource> findAllResourcesInModule(String moduleName, ResourceFilter resourceFilter) {
10841101
return List.copyOf(ModuleUtils.findAllResourcesInModule(moduleName, resourceFilter));
10851102
}
10861103

1104+
/**
1105+
* @since 6.1
1106+
*/
1107+
public static List<Resource> findAllResourcesInModule(Module module, ResourceFilter resourceFilter) {
1108+
return List.copyOf(ModuleUtils.findAllResourcesInModule(module, resourceFilter));
1109+
}
1110+
10871111
/**
10881112
* @since 1.10
10891113
*/

junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,22 @@ public static ModuleSelector selectModule(String moduleName) {
428428
return new ModuleSelector(moduleName.strip());
429429
}
430430

431+
/**
432+
* Create a {@code ModuleSelector} for the supplied module.
433+
*
434+
* <p>The unnamed module is not supported.
435+
*
436+
* @param module the module to select; never {@code null} or blank
437+
* @since 6.1
438+
* @see ModuleSelector
439+
*/
440+
@API(status = STABLE, since = "6.1")
441+
public static ModuleSelector selectModule(Module module) {
442+
Preconditions.notNull(module, "Module must not be null");
443+
Preconditions.condition(module.isNamed(), "Module must be named");
444+
return new ModuleSelector(module);
445+
}
446+
431447
/**
432448
* Create a list of {@code ModuleSelectors} for the supplied module names.
433449
*

junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ModuleSelector.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Optional;
1818

1919
import org.apiguardian.api.API;
20+
import org.jspecify.annotations.Nullable;
2021
import org.junit.platform.commons.util.ToStringBuilder;
2122
import org.junit.platform.engine.DiscoverySelector;
2223
import org.junit.platform.engine.DiscoverySelectorIdentifier;
@@ -33,12 +34,28 @@
3334
@API(status = STABLE, since = "1.1")
3435
public final class ModuleSelector implements DiscoverySelector {
3536

37+
@Nullable
38+
private final Module module;
3639
private final String moduleName;
3740

41+
ModuleSelector(Module module) {
42+
this.module = module;
43+
this.moduleName = module.getName();
44+
}
45+
3846
ModuleSelector(String moduleName) {
47+
this.module = null;
3948
this.moduleName = moduleName;
4049
}
4150

51+
/**
52+
* @return the selected module wrapped in an {@link Optional}.
53+
*/
54+
@API(status = STABLE, since = "6.1")
55+
public Optional<Module> getModule() {
56+
return Optional.ofNullable(module);
57+
}
58+
4259
/**
4360
* Get the selected module name.
4461
*/

junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/ClassContainerSelectorResolver.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public Resolution resolve(ClasspathRootSelector selector, Context context) {
4646

4747
@Override
4848
public Resolution resolve(ModuleSelector selector, Context context) {
49+
if (selector.getModule().isPresent()) {
50+
Module module = selector.getModule().get();
51+
return classSelectors(findAllClassesInModule(module, classFilter, classNameFilter));
52+
}
4953
return classSelectors(findAllClassesInModule(selector.getModuleName(), classFilter, classNameFilter));
5054
}
5155

junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/ResourceContainerSelectorResolver.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ public Resolution resolve(ClasspathRootSelector selector, Context context) {
4949

5050
@Override
5151
public Resolution resolve(ModuleSelector selector, Context context) {
52+
if (selector.getModule().isPresent()) {
53+
Module module = selector.getModule().get();
54+
return resourceSelectors(findAllResourcesInModule(module, resourceFilter));
55+
}
5256
return resourceSelectors(findAllResourcesInModule(selector.getModuleName(), resourceFilter));
5357
}
5458

platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ void findAllClassesInModuleDelegates() {
299299
@Test
300300
void findAllClassesInModulePreconditions() {
301301
assertPreconditionViolationNotNullOrEmptyFor("Module name",
302-
() -> ReflectionSupport.findAllClassesInModule(null, allTypes, allNames));
302+
() -> ReflectionSupport.findAllClassesInModule((String) null, allTypes, allNames));
303303
assertPreconditionViolationNotNullFor("class predicate",
304304
() -> ReflectionSupport.findAllClassesInModule("org.junit.platform.commons", null, allNames));
305305
assertPreconditionViolationNotNullFor("name predicate",

platform-tests/src/test/java/org/junit/platform/commons/support/ResourceSupportTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ void findAllResourcesInModuleDelegates() {
185185
@Test
186186
void findAllResourcesInModulePreconditions() {
187187
assertPreconditionViolationNotNullOrEmptyFor("Module name",
188-
() -> ResourceSupport.findAllResourcesInModule(null, allResources));
188+
() -> ResourceSupport.findAllResourcesInModule((String) null, allResources));
189189
assertPreconditionViolationNotNullFor("Resource filter",
190190
() -> ResourceSupport.findAllResourcesInModule("org.junit.platform.commons", null));
191191
}

0 commit comments

Comments
 (0)