diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml index 2d827a276a..fd9b059062 100644 --- a/.github/workflows/maven-verify.yml +++ b/.github/workflows/maven-verify.yml @@ -50,3 +50,7 @@ jobs: !surefire-its/target/ConsoleOutputIT_*/target/surefire-reports/*-jvmRun*-events.bin timeout-minutes: 600 os-matrix: '[ "ubuntu-latest", "windows-latest", "macos-latest" ]' + maven4-enabled: true + matrix-exclude: '[ + { "jdk": "11", "maven": "4.0.0-rc-5" } + ]' diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CountdownCloseable.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CountdownCloseable.java index 02f7846dfd..d0dbafda9f 100644 --- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CountdownCloseable.java +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CountdownCloseable.java @@ -53,7 +53,7 @@ public synchronized void close() throws IOException { * @throws InterruptedException see {@link Object#wait()} */ public synchronized void awaitClosed() throws InterruptedException { - if (countdown > 0) { + while (countdown > 0) { wait(); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java index 463d8b46e7..e10a16bd6d 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java @@ -76,8 +76,10 @@ public final class MavenLauncher { this.resourceName = resourceName; this.suffix = suffix != null ? suffix : ""; this.cli = cli == null ? null : cli.clone(); - // by default use embedded mode - this.forkJvm = false; + // Use forked mode for Maven 4+ because maven-verifier 2.0.0-M1's embedded mode + // uses reflection against MavenCling.doMain() with an incompatible method signature. + // Once surefire migrates from maven-verifier to maven-executor, this can be removed. + this.forkJvm = isMaven4(); resetGoals(); resetCliOptions(); } @@ -409,6 +411,32 @@ private static Verifier createVerifier(String basedir, String settingsFile, Stri : new Verifier(basedir, settingsFile, false, defaultCliOptions); } + /** + * Detects if the current Maven installation is version 4.x or later by checking for the + * presence of {@code maven-cli-*.jar} in the Maven home lib directory. Maven 4 introduced + * the {@code maven-cli} module which is not present in Maven 3.x installations. + * + * @return {@code true} if Maven 4+ is detected + */ + private static boolean isMaven4() { + String mavenHome = System.getProperty("maven.home", ""); + if (mavenHome.isEmpty()) { + return false; + } + File libDir = new File(mavenHome, "lib"); + if (libDir.isDirectory()) { + String[] files = libDir.list(); + if (files != null) { + for (String file : files) { + if (file.startsWith("maven-cli-")) { + return true; + } + } + } + } + return false; + } + private static File settingsXmlPath() { try { return new File(System.getProperty("maven.settings.file")).getCanonicalFile();