diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java index c5d8aed845c..2b075e0f13c 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java @@ -210,7 +210,13 @@ public class ExecutorTest extends JUnitAdapter { assertEquals(0, result[0].getExitCode()); - assertEquals(expectedCapturedSystemOut(commandWithDiscardedStreams), outputCapture.outLines()); + // If we dump the subprocesses's output, and the command produced both STDOUT and STDERR, + // then the captured STDOUT may contain interleaved command's STDOUT and STDERR, + // not in sequential order (STDOUT followed by STDERR). + // In this case don't check the contents of the captured command's STDOUT. + if (toolProvider || outputCapture.outLines().isEmpty() || (command.stdout().isEmpty() || command.stderr().isEmpty())) { + assertEquals(expectedCapturedSystemOut(commandWithDiscardedStreams), outputCapture.outLines()); + } assertEquals(expectedCapturedSystemErr(commandWithDiscardedStreams), outputCapture.errLines()); assertEquals(expectedResultStdout(commandWithDiscardedStreams), result[0].stdout().getOutput()); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 91625603a2b..ef118e525c5 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -32,6 +32,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.io.StringReader; +import java.io.UncheckedIOException; import java.io.Writer; import java.nio.file.Path; import java.util.ArrayList; @@ -42,12 +43,15 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.util.function.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ExceptionBox; public final class Executor extends CommandArguments { @@ -465,9 +469,37 @@ public final class Executor extends CommandArguments { trace("Execute " + sb.toString() + "..."); Process process = builder.start(); - final var output = combine( - processProcessStream(outputStreamsControl.stdout(), process.getInputStream()), - processProcessStream(outputStreamsControl.stderr(), process.getErrorStream())); + var stdoutGobbler = CompletableFuture.>>supplyAsync(() -> { + try { + return processProcessStream(outputStreamsControl.stdout(), process.getInputStream()); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + + var stderrGobbler = CompletableFuture.>>supplyAsync(() -> { + try { + return processProcessStream(outputStreamsControl.stderr(), process.getErrorStream()); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + + final CommandOutput output; + + try { + output = combine(stdoutGobbler.join(), stderrGobbler.join()); + } catch (CompletionException ex) { + var cause = ex.getCause(); + switch (cause) { + case UncheckedIOException uioex -> { + throw uioex.getCause(); + } + default -> { + throw ExceptionBox.toUnchecked(ExceptionBox.unbox(cause)); + } + } + } final int exitCode = process.waitFor(); trace("Done. Exit code: " + exitCode);