Skip to content

Log invalid search path roots #4823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9d5c59c
feat: log invalid search path roots (#4772)
currenjin Aug 9, 2025
9800997
Merge branch 'main' into feat/issue-4772-log-invalid-roots
currenjin Aug 9, 2025
648a9cd
feat: change log level to WARN for invalid classpath roots (#4772)
currenjin Aug 9, 2025
cb782d9
test: force English locale in execute* tests to match expected logs
currenjin Aug 10, 2025
230c429
test: logsInvalidSearchPathRoots using TrackLogRecords
currenjin Aug 14, 2025
eadc9b7
feat: log and skip only non-existent classpath roots
currenjin Aug 14, 2025
d3317a3
test: add doesNotLogInvalidAdditionalClasspathRoots
currenjin Aug 14, 2025
62243dd
fix: remove unused import
currenjin Aug 14, 2025
9974ad3
fix: lint
currenjin Aug 14, 2025
41b397f
refactor: validate additional classpath entries directly instead of u…
currenjin Aug 14, 2025
0a6ba3d
fix: lint
currenjin Aug 14, 2025
c303e7f
Merge branch 'main' into feat/issue-4772-log-invalid-roots
currenjin Aug 14, 2025
060a399
refactor: simplify classpath root validation logic
currenjin Aug 15, 2025
ccf18ce
test: reformat assertion in DiscoveryRequestCreatorTests
currenjin Aug 15, 2025
83201a1
refactor: validate classpath roots once in createClasspathRootSelectors
currenjin Aug 15, 2025
cf7d4ee
Merge branch 'main' into feat/issue-4772-log-invalid-roots
currenjin Aug 15, 2025
e086c3d
docs: add release notes entry for improved additional classpath root …
currenjin Aug 15, 2025
551422f
Merge branch 'main' into feat/issue-4772-log-invalid-roots
currenjin Aug 16, 2025
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 @@ -24,14 +24,18 @@
import static org.junit.platform.launcher.TagFilter.includeTags;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.ModuleUtils;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ReflectionUtils;
Expand All @@ -49,6 +53,8 @@
*/
class DiscoveryRequestCreator {

private static final Logger logger = LoggerFactory.getLogger(DiscoveryRequestCreator.class);

static LauncherDiscoveryRequestBuilder toDiscoveryRequestBuilder(TestDiscoveryOptions options) {
LauncherDiscoveryRequestBuilder requestBuilder = request();
List<? extends DiscoverySelector> selectors = createDiscoverySelectors(options);
Expand Down Expand Up @@ -86,10 +92,30 @@ private static Set<Path> determineClasspathRoots(TestDiscoveryOptions options) {
() -> "No classpath entries selected");
if (selectedClasspathEntries.isEmpty()) {
Set<Path> rootDirs = new LinkedHashSet<>(ReflectionUtils.getAllClasspathRootDirectories());
rootDirs.addAll(options.getExistingAdditionalClasspathEntries());
return rootDirs;
rootDirs.addAll(options.getAdditionalClasspathEntries());
return validateAndLogInvalidRoots(rootDirs);
}
return validateAndLogInvalidRoots(new LinkedHashSet<>(selectedClasspathEntries));
}

private static Set<Path> validateAndLogInvalidRoots(Set<Path> roots) {
LinkedHashSet<Path> valid = new LinkedHashSet<>();
HashSet<Path> seen = new HashSet<>();

for (Path root : roots) {
if (!seen.add(root))
continue;

boolean exists = Files.exists(root);

if (!exists) {
logger.warn(() -> "Ignoring invalid search path root: %s (exists=%s)".formatted(root, exists));
continue;
}
valid.add(root);
}
return new LinkedHashSet<>(selectedClasspathEntries);

return valid;
}

private static void addFilters(LauncherDiscoveryRequestBuilder requestBuilder, TestDiscoveryOptions options,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@
import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.LogRecord;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.fixtures.TrackLogRecords;
import org.junit.platform.commons.PreconditionViolationException;
import org.junit.platform.commons.logging.LogRecordListener;
import org.junit.platform.console.options.TestDiscoveryOptions;
import org.junit.platform.engine.Filter;
import org.junit.platform.engine.UniqueId;
Expand Down Expand Up @@ -372,6 +376,32 @@ void convertsConfigurationParametersResources() {
assertThat(configurationParameters.get("com.example.prop.second")).contains("second value");
}

@Test
void logsInvalidSearchPathRoots(@TrackLogRecords LogRecordListener listener) {
var opts = new TestDiscoveryOptions();
opts.setScanClasspath(true);
opts.setSelectedClasspathEntries(List.of(Paths.get("/does/not/exist")));

DiscoveryRequestCreator.toDiscoveryRequestBuilder(opts);

assertThat(listener.stream(DiscoveryRequestCreator.class)) //
.map(LogRecord::getMessage) //
.filteredOn(message -> message.contains("/does/not/exist")) //
.hasSize(1);
}

@Test
void logsInvalidAdditionalClasspathRoots(@TrackLogRecords LogRecordListener listener) {
var opts = new TestDiscoveryOptions();
opts.setScanClasspath(true);
opts.setAdditionalClasspathEntries(List.of(Paths.get("/also/does/not/exist")));

DiscoveryRequestCreator.toDiscoveryRequestBuilder(opts);

assertThat(listener.stream(DiscoveryRequestCreator.class)).map(LogRecord::getMessage).filteredOn(
msg -> msg.contains("/also/does/not/exist")).hasSize(1);
}

private LauncherDiscoveryRequest convert() {
return DiscoveryRequestCreator.toDiscoveryRequestBuilder(options).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ void execute(@FilePrefix("console-launcher") OutputFiles outputFiles) throws Exc
.addArguments("-enableassertions") //
.addArguments("-Djava.util.logging.config.file=logging.properties") //
.addArguments("-Djunit.platform.launcher.interceptors.enabled=true") //
.addArguments("-Duser.language=en", "-Duser.country=US") //
.addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone").toString()) //
.addArguments("execute") //
.addArguments("--scan-class-path") //
Expand Down Expand Up @@ -517,6 +518,7 @@ void executeWithJarredTestClasses(@FilePrefix("jar") OutputFiles jarOutputFiles,
.addArguments("-enableassertions") //
.addArguments("-Djava.util.logging.config.file=logging.properties") //
.addArguments("-Djunit.platform.launcher.interceptors.enabled=true") //
.addArguments("-Duser.language=en", "-Duser.country=US") //
.addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone").toString()) //
.addArguments("execute") //
.addArguments("--scan-class-path") //
Expand Down
Loading