This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.22.x by this push:
new 73b4105440a0 [backport camel-4.22.x] camel-launcher: skip sources and
javadoc jars (#27827)
73b4105440a0 is described below
commit 73b4105440a0de137478be4d0865227b706fe0c5
Author: Federico Mariani <[email protected]>
AuthorDate: Fri Oct 16 22:22:49 2026 +0200
[backport camel-4.22.x] camel-launcher: skip sources and javadoc jars
(#27827)
Backport of #27826 to camel-4.22.x: the launch scripts skip sources and
javadoc JARs, and the distribution assemblies leave them out.
It also carries the Windows validator fix of 7ab6c2946729 (CAMEL-24485):
bounded process execution, a shared PowerShell cache, timing diagnostics,
archived surefire reports and a 60-minute job limit. The Windows launcher
script normalizes the selected JAR path, and the POSIX packaging steps use
the pinned Maven wrapper with the snapshot repositories.
AI-generated by Codex on behalf of @Croway.
---
.github/workflows/package-native-validation.yml | 48 ++++++++++++++----
.../src/main/assembly/launcher-content.xml | 2 +
.../src/main/resources/bin/camel.bat | 7 ++-
.../camel-launcher/src/main/resources/bin/camel.sh | 3 +-
.../dsl/jbang/launcher/CamelBatDiscoveryTest.java | 19 +++++++
.../dsl/jbang/launcher/CamelShDiscoveryTest.java | 20 ++++++++
.../dsl/jbang/launcher/WebsiteInstallTest.java | 58 +++++++---------------
.../jbang/launcher/WebsiteInstallerFixture.java | 33 +++++++++++-
8 files changed, 137 insertions(+), 53 deletions(-)
diff --git a/.github/workflows/package-native-validation.yml
b/.github/workflows/package-native-validation.yml
index 4027b4b6c79a..27de46e58c2d 100644
--- a/.github/workflows/package-native-validation.yml
+++ b/.github/workflows/package-native-validation.yml
@@ -41,6 +41,8 @@ concurrency:
permissions:
contents: read
+# Use the project Maven wrapper throughout: runner-provided Maven versions can
differ
+# from the version supported by this branch's build extensions.
jobs:
# ── macOS / Linux (POSIX validators) ──────────────────────────────
posix-validator:
@@ -81,6 +83,16 @@ jobs:
java-version: '21'
cache: 'maven'
+ # Packaging scripts invoke mvn themselves, so pin their PATH entry as
well as
+ # the direct workflow commands. Keep the snapshot profile active in
subprocesses.
+ - name: Pin Maven for packaging subprocesses
+ shell: bash
+ run: |
+ CAMEL_CI_MAVEN_HOME=$(./mvnw -q -B -P apache-snapshots -ntp -N
org.apache.maven.plugins:maven-help-plugin:3.5.1:evaluate \
+ -Dexpression=maven.home -DforceStdout)
+ echo "$CAMEL_CI_MAVEN_HOME/bin" >> "$GITHUB_PATH"
+ echo "MAVEN_ARGS=${MAVEN_ARGS:-} -P apache-snapshots" >>
"$GITHUB_ENV"
+
# camel-repackager-maven-plugin builds the launcher's self-executing
JAR. It is not in the
# -pl list below, so without this step Maven resolves it from the Apache
snapshot repository.
# This workflow only triggers on dsl/camel-jbang/camel-launcher and
tooling/camel-exe changes
@@ -88,7 +100,7 @@ jobs:
- name: Install camel-repackager-maven-plugin (build-time plugin,
unresolvable from this reactor pass)
shell: bash
run: |
- mvn -B -P apache-snapshots -ntp \
+ ./mvnw -B -P apache-snapshots -ntp \
-pl tooling/maven/camel-repackager-maven-plugin install -DskipTests
- name: Build camel-launcher distribution
@@ -98,14 +110,14 @@ jobs:
# published snapshot instead of being rebuilt from source, which is
what previously turned
# this into a ~626-module reactor build. -P apache-snapshots is
required for that resolution.
run: |
- mvn -B -P apache-snapshots -ntp \
+ ./mvnw -B -P apache-snapshots -ntp \
-pl buildingtools,dsl/camel-jbang/camel-launcher install
-DskipTests
- name: Stage a synthetic release version for offline validation
shell: bash
run: |
cd dsl/camel-jbang/camel-launcher
- REAL_VERSION=$(mvn -q -B -ntp
org.apache.maven.plugins:maven-help-plugin:3.5.1:evaluate \
+ REAL_VERSION=$(../../../mvnw -q -B -P apache-snapshots -ntp
org.apache.maven.plugins:maven-help-plugin:3.5.1:evaluate \
-Dexpression=project.version -DforceStdout)
TEST_VERSION="${REAL_VERSION%-SNAPSHOT}"
echo "TEST_VERSION=$TEST_VERSION" >> "$GITHUB_ENV"
@@ -142,14 +154,16 @@ jobs:
# WebsiteInstallTest's PosixShell suite only gets targeted CI coverage
today as a side
# effect of the generic incremental-build check noticing a direct
change under
# dsl/camel-jbang/camel-launcher; a PR that only touches an upstream
dependency wouldn't
- # trigger it. Run it here explicitly so this dedicated validation
workflow covers it too.
+ # trigger it. Run it here explicitly, together with the POSIX launcher
script tests.
run: |
cd dsl/camel-jbang/camel-launcher
- mvn -B -ntp test -pl .
-Dtest=PackageNativeValidationTest,WebsiteInstallTest
+ ../../../mvnw -B -P apache-snapshots -ntp test -pl .
-Dtest=PackageNativeValidationTest,WebsiteInstallTest,CamelShDiscoveryTest,FakeJavaTest
- # ── Windows (install.ps1 unit tests) ──────────────────────────────
+ # ── Windows (installer and launcher script unit tests)
──────────────────────────────
windows-validator:
runs-on: windows-latest
+ # Caps a genuine hang well below GitHub's 6h default; a passing run has
taken up to ~25 minutes.
+ timeout-minutes: 60
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
with:
@@ -169,7 +183,7 @@ jobs:
- name: Install camel-repackager-maven-plugin (build-time plugin,
unresolvable from this reactor pass)
shell: bash
run: |
- mvn -B -P apache-snapshots -ntp \
+ ./mvnw -B -P apache-snapshots -ntp \
-pl tooling/maven/camel-repackager-maven-plugin install -DskipTests
- name: Build camel-launcher module
@@ -179,11 +193,25 @@ jobs:
# published snapshot instead of being rebuilt from source, which is
what previously turned
# this into a ~626-module reactor build. -P apache-snapshots is
required for that resolution.
run: |
- mvn -B -P apache-snapshots -ntp \
+ ./mvnw -B -P apache-snapshots -ntp \
-pl buildingtools,dsl/camel-jbang/camel-launcher install
-DskipTests
- - name: Run Windows installer unit tests
+ - name: Run Windows installer and launcher script unit tests
shell: bash
+ # The PowerShell suite has taken 10-20 minutes on windows-latest,
straddling camel-launcher's 1200s
+ # surefire fork timeout, so slow-but-passing runs were killed. Give
this job's fork more room.
run: |
cd dsl/camel-jbang/camel-launcher
- mvn -B -ntp test -pl . -Dtest=WebsiteInstallTest
+ ../../../mvnw -B -P apache-snapshots -ntp test -pl .
-Dtest=WebsiteInstallTest,CamelBatDiscoveryTest,FakeJavaTest
-Dcamel.surefire.forkTimeout=2700
+
+ # Per-test timings for the PowerShell suite, which runs close to
camel-launcher's surefire fork timeout.
+ # A fork killed on that timeout writes no XML report; the per-process
timings the fixture prints to the
+ # build log cover that case.
+ - name: Archive surefire reports
+ if: always()
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
# v7.0.1
+ with:
+ name: windows-validator-surefire-reports
+ path: dsl/camel-jbang/camel-launcher/target/surefire-reports
+ retention-days: 7
+ if-no-files-found: ignore
diff --git
a/dsl/camel-jbang/camel-launcher/src/main/assembly/launcher-content.xml
b/dsl/camel-jbang/camel-launcher/src/main/assembly/launcher-content.xml
index f648f2f9d0ea..296373b1c045 100644
--- a/dsl/camel-jbang/camel-launcher/src/main/assembly/launcher-content.xml
+++ b/dsl/camel-jbang/camel-launcher/src/main/assembly/launcher-content.xml
@@ -56,6 +56,8 @@
</includes>
<excludes>
<exclude>original-*.jar</exclude>
+ <exclude>*-sources.jar</exclude>
+ <exclude>*-javadoc.jar</exclude>
</excludes>
</fileSet>
<fileSet>
diff --git a/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.bat
b/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.bat
index 692dbea4de26..9d485f9a39f9 100644
--- a/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.bat
+++ b/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.bat
@@ -49,9 +49,12 @@ set "JAVACMD=%CAMEL_JAVACMD%"
@REM Set JVM options if specified
if "%JAVA_OPTS%" == "" set JAVA_OPTS=-Xmx512m
-@REM Find the launcher JAR
+@REM Find the launcher JAR, excluding sources and javadoc
set "LAUNCHER_JAR="
-for %%i in ("%BASEDIR%\camel-launcher-*.jar") do set "LAUNCHER_JAR=%%i"
+for %%i in ("%BASEDIR%\camel-launcher-*.jar") do (
+ echo %%~nxi| findstr /i /e /l /c:"-sources.jar" /c:"-javadoc.jar" > nul
+ if errorlevel 1 if not defined LAUNCHER_JAR set "LAUNCHER_JAR=%%~fi"
+)
@REM Execute Camel CLI, preserving arguments and the child exit code
for %%e in ("%JAVACMD%") do set "_JAVACMD_EXT=%%~xe"
diff --git a/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.sh
b/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.sh
index c5f1fb6fd0c7..36a66c77efab 100644
--- a/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.sh
+++ b/dsl/camel-jbang/camel-launcher/src/main/resources/bin/camel.sh
@@ -100,9 +100,10 @@ then
REPO="$BASEDIR"
fi
-# Find the launcher JAR
+# Find the launcher JAR, excluding sources and javadoc
LAUNCHER_JAR=
for f in "$BASEDIR"/camel-launcher-*.jar; do
+ case "$f" in *-sources.jar|*-javadoc.jar) continue ;; esac
if [ -f "$f" ]; then
LAUNCHER_JAR="$f"
break
diff --git
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelBatDiscoveryTest.java
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelBatDiscoveryTest.java
index 424311576275..03883353c0eb 100644
---
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelBatDiscoveryTest.java
+++
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelBatDiscoveryTest.java
@@ -76,6 +76,25 @@ class CamelBatDiscoveryTest {
return javaHome;
}
+ @Test
+ void skipsSourcesAndJavadocJars(@TempDir Path base) throws Exception {
+ Path h = home(Files.createDirectories(base.resolve("launcher with
spaces")));
+ Files.writeString(h.resolve("camel-launcher-9.9.9-sources.jar"),
"sources");
+ Files.writeString(h.resolve("camel-launcher-zzz-sources.jar"),
"sources");
+ Files.writeString(h.resolve("camel-launcher-9.9.9-javadoc.jar"),
"javadoc");
+ Files.writeString(h.resolve("camel-launcher-zzz-javadoc.jar"),
"javadoc");
+ Path java = FakeJava.writeFakeJava(base, "java", JAVA17, 0, "JAVACMD");
+ Map<String, String> env = isolatedEnvironment();
+ env.put("JAVACMD", java.toString());
+
+ FakeJava.Result r = FakeJava.run(h.resolve("camel.bat"), env,
"hawtio");
+
+ assertEquals(0, r.exitCode(), r.stderr());
+
assertTrue(r.stdout().contains(h.resolve("camel-launcher-9.9.9.jar").toString()),
r.stdout());
+ assertFalse(r.stdout().contains("-sources.jar"), r.stdout());
+ assertFalse(r.stdout().contains("-javadoc.jar"), r.stdout());
+ }
+
@Test
void acceptsJava17ViaJavacmd(@TempDir Path base) throws Exception {
Path h = home(base);
diff --git
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelShDiscoveryTest.java
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelShDiscoveryTest.java
index ad2735ed362c..08fac4adf315 100644
---
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelShDiscoveryTest.java
+++
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelShDiscoveryTest.java
@@ -56,6 +56,26 @@ class CamelShDiscoveryTest {
return pathDir + ":/usr/bin:/bin";
}
+ @Test
+ void skipsSourcesAndJavadocJars(@TempDir Path base) throws Exception {
+ Path h = home(Files.createDirectories(base.resolve("launcher with
spaces")));
+ Files.writeString(h.resolve("camel-launcher-9.9.9-sources.jar"),
"sources");
+ Files.writeString(h.resolve("camel-launcher-zzz-sources.jar"),
"sources");
+ Files.writeString(h.resolve("camel-launcher-9.9.9-javadoc.jar"),
"javadoc");
+ Files.writeString(h.resolve("camel-launcher-zzz-javadoc.jar"),
"javadoc");
+ Path java = FakeJava.writeFakeJava(base, "java", JAVA17, 0, "JAVACMD");
+ Map<String, String> env = new HashMap<>();
+ env.put("LC_ALL", "C");
+ env.put("JAVACMD", java.toString());
+
+ FakeJava.Result r = FakeJava.run(h.resolve("camel.sh"), env, "hawtio");
+
+ assertEquals(0, r.exitCode(), r.stderr());
+
assertTrue(r.stdout().contains(h.resolve("camel-launcher-9.9.9.jar").toString()),
r.stdout());
+ assertFalse(r.stdout().contains("-sources.jar"), r.stdout());
+ assertFalse(r.stdout().contains("-javadoc.jar"), r.stdout());
+ }
+
@Test
void acceptsJava17ViaJavacmd(@TempDir Path base) throws Exception {
Path h = home(base);
diff --git
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallTest.java
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallTest.java
index 0fbda6496e9d..a514a7c10828 100644
---
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallTest.java
+++
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallTest.java
@@ -34,7 +34,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterEach;
@@ -152,11 +151,8 @@ class WebsiteInstallTest {
Path versionDir = home.resolve(".local/share/camel-cli/versions/"
+ version);
assertTrue(Files.isDirectory(versionDir), "expected version
directory " + versionDir);
- Process check = new ProcessBuilder("/bin/sh", shim.toString(),
"version")
- .redirectErrorStream(true)
- .start();
- String output = new String(check.getInputStream().readAllBytes(),
StandardCharsets.UTF_8);
- check.waitFor();
+ String output = WebsiteInstallerFixture.execute(
+ new ProcessBuilder("/bin/sh", shim.toString(),
"version").redirectErrorStream(true)).stdout();
assertTrue(output.contains("Camel " + version), output);
}
@@ -672,9 +668,8 @@ class WebsiteInstallTest {
+ "if ($path) { $kind = $k.GetValueKind('Path'); "
+ "$kept = ($path -split ';') | Where-Object { $_
-and (-not ($dirs -icontains $_)) }; "
+ "$k.SetValue('Path', ($kept -join ';'), $kind) }
$k.Close() }");
- Process cleanup = new ProcessBuilder("powershell", "-NoProfile",
"-Command", script.toString())
- .redirectErrorStream(true).start();
- cleanup.waitFor(30, TimeUnit.SECONDS);
+ WebsiteInstallerFixture.execute(
+ new ProcessBuilder("powershell", "-NoProfile", "-Command",
script.toString()).redirectErrorStream(true));
}
private WebsiteInstallerFixture.Result install(
@@ -716,11 +711,8 @@ class WebsiteInstallTest {
assertTrue(Files.isDirectory(versionDir(home, version)),
"expected version directory " + versionDir(home, version));
- Process check = new ProcessBuilder("cmd.exe", "/c",
shim.toString(), "version")
- .redirectErrorStream(true)
- .start();
- String output = new String(check.getInputStream().readAllBytes(),
StandardCharsets.UTF_8);
- check.waitFor(30, TimeUnit.SECONDS);
+ String output = WebsiteInstallerFixture.execute(
+ new ProcessBuilder("cmd.exe", "/c", shim.toString(),
"version").redirectErrorStream(true)).stdout();
assertTrue(output.contains("Camel " + version), output);
}
@@ -740,13 +732,10 @@ class WebsiteInstallTest {
}
private static String queryEnvironmentPath(String scope) throws
Exception {
- Process p = new ProcessBuilder(
+ return WebsiteInstallerFixture.execute(new ProcessBuilder(
"powershell", "-NoProfile", "-Command",
"[Environment]::GetEnvironmentVariable('Path','" + scope +
"')")
- .redirectErrorStream(true).start();
- String out = new String(p.getInputStream().readAllBytes(),
StandardCharsets.UTF_8).trim();
- p.waitFor(30, TimeUnit.SECONDS);
- return out;
+ .redirectErrorStream(true)).stdout().trim();
}
private static long countOccurrencesCaseInsensitive(String path,
String dir) {
@@ -760,15 +749,12 @@ class WebsiteInstallTest {
// Reads HKCU\Environment\Path without expanding %VAR% references,
returning "" when unset.
private static String readUserPathRaw() throws Exception {
- Process p = new ProcessBuilder(
+ return WebsiteInstallerFixture.execute(new ProcessBuilder(
"powershell", "-NoProfile", "-Command",
"$k =
[Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment'); "
+ "if ($k) {
[Console]::Out.Write($k.GetValue('Path', '', "
- +
"[Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames));
$k.Close() }")
- .start();
- String out = new String(p.getInputStream().readAllBytes(),
StandardCharsets.UTF_8);
- p.waitFor(30, TimeUnit.SECONDS);
- return out;
+ +
"[Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames));
$k.Close() }"))
+ .stdout();
}
// Writes HKCU\Environment\Path as a REG_EXPAND_SZ value; the value is
passed via the environment
@@ -781,21 +767,18 @@ class WebsiteInstallTest {
+
"[Microsoft.Win32.RegistryValueKind]::ExpandString); $k.Close()")
.redirectErrorStream(true);
pb.environment().put("CAMEL_TEST_USERPATH", value);
- Process p = pb.start();
- String out = new String(p.getInputStream().readAllBytes(),
StandardCharsets.UTF_8);
- if (!p.waitFor(30, TimeUnit.SECONDS) || p.exitValue() != 0) {
- throw new IllegalStateException("failed to seed user PATH: " +
out);
+ WebsiteInstallerFixture.Result r =
WebsiteInstallerFixture.execute(pb);
+ if (r.exit() != 0) {
+ throw new IllegalStateException("failed to seed user PATH: " +
r.stdout());
}
}
private static void deleteUserPath() throws Exception {
- Process p = new ProcessBuilder(
+ WebsiteInstallerFixture.execute(new ProcessBuilder(
"powershell", "-NoProfile", "-Command",
"$k =
[Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true); "
+ "if ($k) {
$k.DeleteValue('Path', $false); $k.Close() }")
- .redirectErrorStream(true).start();
- p.getInputStream().readAllBytes();
- p.waitFor(30, TimeUnit.SECONDS);
+ .redirectErrorStream(true));
}
@Test
@@ -1039,14 +1022,11 @@ class WebsiteInstallTest {
// ("bar baz") trips cmd.exe's quote-stripping rule (it only
preserves quotes when there are
// exactly two), which would unquote the space in "Apache
Camel" and break the call. A bare
// command name resolved through PATH+PATHEXT avoids that
quirk and mirrors real usage.
- Process argsProc = shimProcess(binDir, "echo-args", "foo",
"bar baz").start();
- String argsOut = new
String(argsProc.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
- argsProc.waitFor(30, TimeUnit.SECONDS);
+ String argsOut =
WebsiteInstallerFixture.execute(shimProcess(binDir, "echo-args", "foo", "bar
baz"))
+ .stdout();
assertTrue(argsOut.contains("foo") && argsOut.contains("bar
baz"), argsOut);
- Process exitProc = shimProcess(binDir, "exit-code",
"7").start();
- exitProc.waitFor(30, TimeUnit.SECONDS);
- assertEquals(7, exitProc.exitValue());
+ assertEquals(7,
WebsiteInstallerFixture.execute(shimProcess(binDir, "exit-code", "7")).exit());
}
}
diff --git
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallerFixture.java
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallerFixture.java
index a94857d9b708..996e2eddf74f 100644
---
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallerFixture.java
+++
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/WebsiteInstallerFixture.java
@@ -64,6 +64,8 @@ final class WebsiteInstallerFixture implements AutoCloseable {
private static final String KEY_ALIAS = "camel-installer-test";
private static final String DEFAULT_BASE_VERSION = "9.9.9";
private static final Duration PROCESS_TIMEOUT = Duration.ofSeconds(60);
+ private static final Path POWERSHELL_MODULE_ANALYSIS_CACHE
+ = Path.of("target", "powershell",
"ModuleAnalysisCache").toAbsolutePath();
record Result(int exit, String stdout, String stderr) {
}
@@ -446,6 +448,20 @@ final class WebsiteInstallerFixture implements
AutoCloseable {
if (pathExt != null) {
pb.environment().put("PATHEXT", pathExt);
}
+ // Without TEMP/TMP, .NET falls back to USERPROFILE (the fresh
per-test home) for the scratch
+ // files Add-Type's C# compile writes on every install.ps1 run.
install.ps1 itself never stages
+ // anything under the temp directory, so passing the runner's
through does not affect isolation.
+ for (String name : List.of("TEMP", "TMP")) {
+ String value = System.getenv(name);
+ if (value != null) {
+ pb.environment().put(name, value);
+ }
+ }
+ // PowerShell keeps its module analysis cache under LOCALAPPDATA,
which every test points at a
+ // fresh home, so each powershell.exe launch would rebuild it from
scratch when auto-loading
+ // Expand-Archive / Get-FileHash. Share one cache file across the
whole test run instead.
+
Files.createDirectories(POWERSHELL_MODULE_ANALYSIS_CACHE.getParent());
+ pb.environment().put("PSModuleAnalysisCachePath",
POWERSHELL_MODULE_ANALYSIS_CACHE.toString());
}
pb.environment().putAll(env);
String home = env.get("HOME");
@@ -454,7 +470,16 @@ final class WebsiteInstallerFixture implements
AutoCloseable {
// wherever the test JVM happens to be running from.
pb.directory(Path.of(home).toFile());
}
+ return execute(pb);
+ }
+ /**
+ * Runs {@code pb} with stdout and stderr drained on background threads,
so a chatty or stuck child can never block
+ * the test past {@link #PROCESS_TIMEOUT}: reading a stream to EOF before
{@code waitFor} would wait for as long as
+ * the child (or any grandchild inheriting its handles) keeps the pipe
open.
+ */
+ static Result execute(ProcessBuilder pb) throws Exception {
+ long start = System.nanoTime();
Process process = pb.start();
ExecutorService collectors = Executors.newFixedThreadPool(2);
try {
@@ -463,7 +488,7 @@ final class WebsiteInstallerFixture implements
AutoCloseable {
process.getOutputStream().close();
if (!process.waitFor(PROCESS_TIMEOUT.toSeconds(),
TimeUnit.SECONDS)) {
process.destroyForcibly();
- throw new IllegalStateException("installer did not exit in
time");
+ throw new IllegalStateException("process did not exit in time:
" + pb.command());
}
String out = new String(await(stdout), StandardCharsets.UTF_8);
String err = new String(await(stderr), StandardCharsets.UTF_8);
@@ -474,6 +499,12 @@ final class WebsiteInstallerFixture implements
AutoCloseable {
}
collectors.shutdownNow();
collectors.awaitTermination(10, TimeUnit.SECONDS);
+ // Surefire streams test stdout to the build log as it happens, so
these timings survive even when
+ // the fork is killed by forkedProcessTimeoutInSeconds and no XML
report is ever written.
+ String command = String.join(" ", pb.command());
+ System.out.printf("[WebsiteInstallerFixture] %d ms: %s%n",
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start),
+ command.length() > 160 ? command.substring(0, 160) + "..."
: command);
}
}