1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.exec.issues;
19
20 import java.io.ByteArrayOutputStream;
21 import java.io.PipedInputStream;
22 import java.io.PipedOutputStream;
23 import java.time.Duration;
24
25 import org.apache.commons.exec.CommandLine;
26 import org.apache.commons.exec.DefaultExecuteResultHandler;
27 import org.apache.commons.exec.DefaultExecutor;
28 import org.apache.commons.exec.Executor;
29 import org.apache.commons.exec.PumpStreamHandler;
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.api.condition.DisabledOnOs;
32
33 /**
34 * Test EXEC-44 (https://issues.apache.org/jira/browse/EXEC-44).
35 */
36 public class Exec49Test {
37
38 private static final Duration WAIT = Duration.ofSeconds(10);
39 private final Executor exec = DefaultExecutor.builder().get();
40
41 /**
42 * The issue was detected when trying to capture stdout/stderr with a PipedOutputStream and then pass that to a PipedInputStream. The following code will
43 * produce the error. The reason for the error is the PipedOutputStream is not being closed correctly, causing the PipedInputStream to break.
44 *
45 * @throws Exception the test failed
46 */
47 @Test
48 @DisabledOnOs(org.junit.jupiter.api.condition.OS.WINDOWS)
49 public void testExec49_1() throws Exception {
50 final CommandLine cl = CommandLine.parse("/bin/ls");
51 cl.addArgument("/opt");
52 // redirect stdout/stderr to pipedOutputStream
53 try (PipedOutputStream pipedOutputStream = new PipedOutputStream()) {
54 final PumpStreamHandler psh = new PumpStreamHandler(pipedOutputStream);
55 exec.setStreamHandler(psh);
56 // start an asynchronous process to enable the main thread
57 System.out.println("Preparing to execute process - commandLine=" + cl.toString());
58 final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
59 exec.execute(cl, handler);
60 System.out.println("Process spun off successfully - process=" + cl.getExecutable());
61 try (PipedInputStream pis = new PipedInputStream(pipedOutputStream)) {
62 while (pis.read() >= 0) {
63 // System.out.println("pis.available() " + pis.available());
64 // System.out.println("x " + x);
65 }
66 }
67 handler.waitFor(WAIT);
68 handler.getExitValue(); // will fail if process has not finished
69 }
70 }
71
72 /**
73 * The issue was detected when trying to capture stdout with a PipedOutputStream and then pass that to a PipedInputStream. The following code will produce
74 * the error. The reason for the error is the PipedOutputStream is not being closed correctly, causing the PipedInputStream to break.
75 *
76 * @throws Exception the test failed
77 */
78 @Test
79 @DisabledOnOs(org.junit.jupiter.api.condition.OS.WINDOWS)
80 public void testExec49_2() throws Exception {
81 final CommandLine cl = CommandLine.parse("/bin/ls");
82 cl.addArgument("/opt");
83 // redirect only stdout to pipedOutputStream
84 try (PipedOutputStream pipedOutputStream = new PipedOutputStream()) {
85 final PumpStreamHandler psh = new PumpStreamHandler(pipedOutputStream, new ByteArrayOutputStream());
86 exec.setStreamHandler(psh);
87 // start an asynchronous process to enable the main thread
88 System.out.println("Preparing to execute process - commandLine=" + cl.toString());
89 final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
90 exec.execute(cl, handler);
91 System.out.println("Process spun off successfully - process=" + cl.getExecutable());
92 try (PipedInputStream pis = new PipedInputStream(pipedOutputStream)) {
93 while (pis.read() >= 0) {
94 // System.out.println("pis.available() " + pis.available());
95 // System.out.println("x " + x);
96 }
97 }
98 handler.waitFor(WAIT);
99 handler.getExitValue(); // will fail if process has not finished
100 }
101 }
102
103 }