View Javadoc
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    *      http://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 static org.junit.jupiter.api.Assertions.assertThrows;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  import static org.junit.jupiter.api.Assumptions.assumeFalse;
23  import static org.junit.jupiter.api.Assumptions.assumeTrue;
24  
25  import java.io.File;
26  import java.util.concurrent.TimeUnit;
27  
28  import org.apache.commons.exec.AbstractExecTest;
29  import org.apache.commons.exec.CommandLine;
30  import org.apache.commons.exec.DefaultExecutor;
31  import org.apache.commons.exec.ExecuteException;
32  import org.apache.commons.exec.ExecuteWatchdog;
33  import org.apache.commons.exec.OS;
34  import org.apache.commons.exec.PumpStreamHandler;
35  import org.junit.jupiter.api.Test;
36  import org.junit.jupiter.api.Timeout;
37  
38  /**
39   * Test to show that watchdog can destroy 'sudo' and 'sleep'.
40   *
41   * @see <a href="https://issues.apache.org/jira/browse/EXEC-65">EXEC-65</a>
42   */
43  public class Exec65Test extends AbstractExecTest {
44  
45      /**
46       * This test currently only works for macOS X
47       * <ul>
48       * <li>Linux hangs on the process stream while the process is finished</li>
49       * <li>Windows seems to have similar problems</li>
50       * </ul>
51       *
52       * @TODO Fix tests for Windows & Linux
53       */
54      @Test
55      @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
56      public void testExec65WithSleepUsingShellScript() throws Exception {
57          assumeTrue(OS.isFamilyMac());
58          final DefaultExecutor executor = DefaultExecutor.builder().get();
59          executor.setStreamHandler(new PumpStreamHandler(System.out, System.err));
60          executor.setWatchdog(new ExecuteWatchdog(WATCHDOG_TIMEOUT));
61          final CommandLine command = new CommandLine(resolveTestScript("sleep"));
62  
63          assertThrows(ExecuteException.class, () -> executor.execute(command));
64      }
65  
66      /**
67       * This is the original code snippet from the JIRA to show that killing the process actually works with JDK only but it does not re-direct any streams.
68       */
69      @Test
70      @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
71      public void testExec65WithSleepUsingShellScriptAndJDKOnly() throws Exception {
72  
73          final Process process = Runtime.getRuntime().exec(resolveTestScript("sleep").getAbsolutePath());
74          Thread.sleep(WATCHDOG_TIMEOUT);
75  
76          process.destroy();
77  
78          process.waitFor();
79  
80          assertTrue(process.exitValue() != 0);
81      }
82  
83      /**
84       * Please note that this tests make assumptions about the environment. It assumes that user "root" exists and that the current user is not a "sudoer"
85       * already (thereby requiring a password).
86       */
87      @Test
88      @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
89      public void testExec65WithSudoUsingShellScript() throws Exception {
90          assumeFalse(new File(".").getAbsolutePath().contains("travis"),
91                  "Test is skipped on travis, because we have to be a sudoer to make the other tests pass.");
92          // TODO Fails on GitHub
93          assumeTrue(System.getenv("GITHUB_WORKFLOW") == null);
94          if (!OS.isFamilyUnix()) {
95              throw new ExecuteException(testNotSupportedForCurrentOperatingSystem(), 0);
96          }
97          final DefaultExecutor executor = DefaultExecutor.builder().get();
98          executor.setStreamHandler(new PumpStreamHandler(System.out, System.err, System.in));
99          executor.setWatchdog(new ExecuteWatchdog(WATCHDOG_TIMEOUT));
100         final CommandLine command = new CommandLine(resolveTestScript("issues", "exec-65"));
101 
102         assertThrows(ExecuteException.class, () -> executor.execute(command));
103     }
104 
105     @Test
106     @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
107     public void testExec65WitSleepUsingSleepCommandDirectly() throws Exception {
108 
109         if (!OS.isFamilyUnix()) {
110             throw new ExecuteException(testNotSupportedForCurrentOperatingSystem(), 0);
111         }
112         final ExecuteWatchdog watchdog = new ExecuteWatchdog(WATCHDOG_TIMEOUT);
113         final DefaultExecutor executor = DefaultExecutor.builder().get();
114         final CommandLine command = new CommandLine("sleep");
115         command.addArgument("60");
116         executor.setStreamHandler(new PumpStreamHandler(System.out, System.err));
117         executor.setWatchdog(watchdog);
118 
119         assertThrows(ExecuteException.class, () -> executor.execute(command));
120     }
121 }