23
24 package jdk.test.lib.process;
25
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.io.PrintStream;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.concurrent.CountDownLatch;
35 import java.util.Map;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.TimeoutException;
40 import java.util.function.Predicate;
41 import java.util.function.Consumer;
42 import java.util.stream.Collectors;
43
44 import jdk.test.lib.JDKToolFinder;
45 import jdk.test.lib.Utils;
46
47 public final class ProcessTools {
48 private static final class LineForwarder extends StreamPumper.LinePump {
49 private final PrintStream ps;
50 private final String prefix;
51 LineForwarder(String prefix, PrintStream os) {
52 this.ps = os;
53 this.prefix = prefix;
54 }
55 @Override
56 protected void processLine(String line) {
57 ps.println("[" + prefix + "] " + line);
58 }
59 }
60
61 private ProcessTools() {
62 }
63
64 /**
65 * Pumps stdout and stderr from running the process into a String.
66 *
67 * @param processBuilder ProcessBuilder to run.
68 * @return Output from process.
69 * @throws IOException If an I/O error occurs.
70 */
71 public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
72 return getOutput(processBuilder.start());
73 }
74
75 /**
76 * Pumps stdout and stderr the running process into a String.
77 *
78 * @param process Process to pump.
79 * @return Output from process.
80 * @throws IOException If an I/O error occurs.
81 */
82 public static OutputBuffer getOutput(Process process) throws IOException {
83 ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
84 ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
85 StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
86 StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
87 Thread outPumperThread = new Thread(outPumper);
88 Thread errPumperThread = new Thread(errPumper);
89
90 outPumperThread.setDaemon(true);
91 errPumperThread.setDaemon(true);
92
184 * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to
185 * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
186 * Used to determine the moment the target app is
187 * properly warmed-up.
188 * It can be null - in that case the warmup is skipped.
189 * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
190 * @param unit The timeout {@linkplain TimeUnit}
191 * @return Returns the initialized {@linkplain Process}
192 * @throws IOException
193 * @throws InterruptedException
194 * @throws TimeoutException
195 */
196 public static Process startProcess(String name,
197 ProcessBuilder processBuilder,
198 final Consumer<String> lineConsumer,
199 final Predicate<String> linePredicate,
200 long timeout,
201 TimeUnit unit)
202 throws IOException, InterruptedException, TimeoutException {
203 System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" ")));
204 Process p = processBuilder.start();
205 StreamPumper stdout = new StreamPumper(p.getInputStream());
206 StreamPumper stderr = new StreamPumper(p.getErrorStream());
207
208 stdout.addPump(new LineForwarder(name, System.out));
209 stderr.addPump(new LineForwarder(name, System.err));
210 if (lineConsumer != null) {
211 StreamPumper.LinePump pump = new StreamPumper.LinePump() {
212 @Override
213 protected void processLine(String line) {
214 lineConsumer.accept(line);
215 }
216 };
217 stdout.addPump(pump);
218 stderr.addPump(pump);
219 }
220
221
222 CountDownLatch latch = new CountDownLatch(1);
223 if (linePredicate != null) {
224 StreamPumper.LinePump pump = new StreamPumper.LinePump() {
376 /**
377 * @see #executeTestJvm(String...)
378 * @param cmds User specified arguments.
379 * @return The output from the process.
380 */
381 public static OutputAnalyzer executeTestJava(String... cmds) throws Exception {
382 return executeTestJvm(cmds);
383 }
384
385 /**
386 * Executes a process, waits for it to finish and returns the process output.
387 * The process will have exited before this method returns.
388 * @param pb The ProcessBuilder to execute.
389 * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
390 */
391 public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception {
392 OutputAnalyzer output = null;
393 Process p = null;
394 boolean failed = false;
395 try {
396 p = pb.start();
397 output = new OutputAnalyzer(p);
398 p.waitFor();
399
400 return output;
401 } catch (Throwable t) {
402 if (p != null) {
403 p.destroyForcibly().waitFor();
404 }
405
406 failed = true;
407 System.out.println("executeProcess() failed: " + t);
408 throw t;
409 } finally {
410 if (failed) {
411 System.err.println(getProcessLog(pb, output));
412 }
413 }
414 }
415
416 /**
478 }
479
480 /**
481 * Executes a process, waits for it to finish, prints the process output
482 * to stdout and returns the process output.
483 *
484 * The process will have exited before this method returns.
485 *
486 * @param pb The ProcessBuilder to execute.
487 * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
488 */
489 public static OutputAnalyzer executeCommand(ProcessBuilder pb)
490 throws Throwable {
491 String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
492 System.out.println("Command line: [" + cmdLine + "]");
493 OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
494 System.out.println(analyzer.getOutput());
495 return analyzer;
496 }
497
498 private static class ProcessImpl extends Process {
499
500 private final Process p;
501 private final Future<Void> stdoutTask;
502 private final Future<Void> stderrTask;
503
504 public ProcessImpl(Process p, Future<Void> stdoutTask, Future<Void> stderrTask) {
505 this.p = p;
506 this.stdoutTask = stdoutTask;
507 this.stderrTask = stderrTask;
508 }
509
510 @Override
511 public OutputStream getOutputStream() {
512 return p.getOutputStream();
513 }
514
515 @Override
516 public InputStream getInputStream() {
517 return p.getInputStream();
|
23
24 package jdk.test.lib.process;
25
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.io.PrintStream;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.concurrent.CountDownLatch;
35 import java.util.Map;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.TimeoutException;
40 import java.util.function.Predicate;
41 import java.util.function.Consumer;
42 import java.util.stream.Collectors;
43 import java.security.AccessController;
44 import java.security.PrivilegedActionException;
45 import java.security.PrivilegedExceptionAction;
46
47 import jdk.test.lib.JDKToolFinder;
48 import jdk.test.lib.Utils;
49
50 public final class ProcessTools {
51 private static final class LineForwarder extends StreamPumper.LinePump {
52 private final PrintStream ps;
53 private final String prefix;
54 LineForwarder(String prefix, PrintStream os) {
55 this.ps = os;
56 this.prefix = prefix;
57 }
58 @Override
59 protected void processLine(String line) {
60 ps.println("[" + prefix + "] " + line);
61 }
62 }
63
64 private ProcessTools() {
65 }
66
67 /**
68 * Pumps stdout and stderr from running the process into a String.
69 *
70 * @param processBuilder ProcessBuilder to run.
71 * @return Output from process.
72 * @throws IOException If an I/O error occurs.
73 */
74 public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
75 return getOutput(privilegedStart(processBuilder));
76 }
77
78 /**
79 * Pumps stdout and stderr the running process into a String.
80 *
81 * @param process Process to pump.
82 * @return Output from process.
83 * @throws IOException If an I/O error occurs.
84 */
85 public static OutputBuffer getOutput(Process process) throws IOException {
86 ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
87 ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
88 StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
89 StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
90 Thread outPumperThread = new Thread(outPumper);
91 Thread errPumperThread = new Thread(errPumper);
92
93 outPumperThread.setDaemon(true);
94 errPumperThread.setDaemon(true);
95
187 * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to
188 * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
189 * Used to determine the moment the target app is
190 * properly warmed-up.
191 * It can be null - in that case the warmup is skipped.
192 * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
193 * @param unit The timeout {@linkplain TimeUnit}
194 * @return Returns the initialized {@linkplain Process}
195 * @throws IOException
196 * @throws InterruptedException
197 * @throws TimeoutException
198 */
199 public static Process startProcess(String name,
200 ProcessBuilder processBuilder,
201 final Consumer<String> lineConsumer,
202 final Predicate<String> linePredicate,
203 long timeout,
204 TimeUnit unit)
205 throws IOException, InterruptedException, TimeoutException {
206 System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" ")));
207 Process p = privilegedStart(processBuilder);
208 StreamPumper stdout = new StreamPumper(p.getInputStream());
209 StreamPumper stderr = new StreamPumper(p.getErrorStream());
210
211 stdout.addPump(new LineForwarder(name, System.out));
212 stderr.addPump(new LineForwarder(name, System.err));
213 if (lineConsumer != null) {
214 StreamPumper.LinePump pump = new StreamPumper.LinePump() {
215 @Override
216 protected void processLine(String line) {
217 lineConsumer.accept(line);
218 }
219 };
220 stdout.addPump(pump);
221 stderr.addPump(pump);
222 }
223
224
225 CountDownLatch latch = new CountDownLatch(1);
226 if (linePredicate != null) {
227 StreamPumper.LinePump pump = new StreamPumper.LinePump() {
379 /**
380 * @see #executeTestJvm(String...)
381 * @param cmds User specified arguments.
382 * @return The output from the process.
383 */
384 public static OutputAnalyzer executeTestJava(String... cmds) throws Exception {
385 return executeTestJvm(cmds);
386 }
387
388 /**
389 * Executes a process, waits for it to finish and returns the process output.
390 * The process will have exited before this method returns.
391 * @param pb The ProcessBuilder to execute.
392 * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
393 */
394 public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception {
395 OutputAnalyzer output = null;
396 Process p = null;
397 boolean failed = false;
398 try {
399 p = privilegedStart(pb);
400 output = new OutputAnalyzer(p);
401 p.waitFor();
402
403 return output;
404 } catch (Throwable t) {
405 if (p != null) {
406 p.destroyForcibly().waitFor();
407 }
408
409 failed = true;
410 System.out.println("executeProcess() failed: " + t);
411 throw t;
412 } finally {
413 if (failed) {
414 System.err.println(getProcessLog(pb, output));
415 }
416 }
417 }
418
419 /**
481 }
482
483 /**
484 * Executes a process, waits for it to finish, prints the process output
485 * to stdout and returns the process output.
486 *
487 * The process will have exited before this method returns.
488 *
489 * @param pb The ProcessBuilder to execute.
490 * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
491 */
492 public static OutputAnalyzer executeCommand(ProcessBuilder pb)
493 throws Throwable {
494 String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
495 System.out.println("Command line: [" + cmdLine + "]");
496 OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
497 System.out.println(analyzer.getOutput());
498 return analyzer;
499 }
500
501 private static Process privilegedStart(ProcessBuilder pb) throws IOException {
502 try {
503 return AccessController.doPrivileged(
504 (PrivilegedExceptionAction<Process>) () -> pb.start());
505 } catch (PrivilegedActionException e) {
506 @SuppressWarnings("unchecked")
507 IOException t = (IOException) e.getException();
508 throw t;
509 }
510 }
511
512 private static class ProcessImpl extends Process {
513
514 private final Process p;
515 private final Future<Void> stdoutTask;
516 private final Future<Void> stderrTask;
517
518 public ProcessImpl(Process p, Future<Void> stdoutTask, Future<Void> stderrTask) {
519 this.p = p;
520 this.stdoutTask = stdoutTask;
521 this.stderrTask = stderrTask;
522 }
523
524 @Override
525 public OutputStream getOutputStream() {
526 return p.getOutputStream();
527 }
528
529 @Override
530 public InputStream getInputStream() {
531 return p.getInputStream();
|