View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.commons.exec.issues;
21  
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  import static org.junit.jupiter.api.Assumptions.assumeFalse;
25  import static org.junit.jupiter.api.Assumptions.assumeTrue;
26  
27  import java.io.File;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.apache.commons.exec.AbstractExecTest;
31  import org.apache.commons.exec.CommandLine;
32  import org.apache.commons.exec.DefaultExecutor;
33  import org.apache.commons.exec.ExecuteException;
34  import org.apache.commons.exec.ExecuteWatchdog;
35  import org.apache.commons.exec.PumpStreamHandler;
36  import org.junit.jupiter.api.Test;
37  import org.junit.jupiter.api.Timeout;
38  import org.junit.jupiter.api.condition.DisabledOnOs;
39  import org.junit.jupiter.api.condition.EnabledOnOs;
40  
41  /**
42   * Test to show that watchdog can destroy 'sudo' and 'sleep'.
43   *
44   * @see <a href="https://issues.apache.org/jira/browse/EXEC-65">EXEC-65</a>
45   */
46  class Exec65Test extends AbstractExecTest {
47  
48      /**
49       * This test currently only works for Mac OS X
50       * <ul>
51       * <li>Linux hangs on the process stream while the process is finished</li>
52       * <li>Windows seems to have similar problems</li>
53       * </ul>
54       */
55      @Test
56      // TODO: Fix test for Windows & Linux
57      @EnabledOnOs(value = org.junit.jupiter.api.condition.OS.MAC)
58      @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
59      void testExec65WithSleepUsingShellScript() throws Exception {
60          final DefaultExecutor executor = DefaultExecutor.builder().get();
61          executor.setStreamHandler(new PumpStreamHandler(System.out, System.err));
62          executor.setWatchdog(new ExecuteWatchdog(WATCHDOG_TIMEOUT));
63          final CommandLine command = new CommandLine(resolveTestScript("sleep"));
64  
65          assertThrows(ExecuteException.class, () -> executor.execute(command));
66      }
67  
68      /**
69       * This is the original code snippet from the JIRA to show that killing the process actually works with JDK only,
70       * but it does not re-direct any streams.
71       */
72      @Test
73      @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
74      void testExec65WithSleepUsingShellScriptAndJDKOnly() throws Exception {
75  
76          final Process process = Runtime.getRuntime().exec(resolveTestScript("sleep").getAbsolutePath());
77          Thread.sleep(WATCHDOG_TIMEOUT);
78  
79          process.destroy();
80  
81          process.waitFor();
82  
83          assertTrue(process.exitValue() != 0);
84      }
85  
86      /**
87       * 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"
88       * already (thereby requiring a password).
89       */
90      @Test
91      @DisabledOnOs(org.junit.jupiter.api.condition.OS.WINDOWS)
92      @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
93      void testExec65WithSudoUsingShellScript() throws Exception {
94          assumeFalse(new File(".").getAbsolutePath().contains("travis"),
95                  "Test is skipped on travis, because we have to be a sudoer to make the other tests pass.");
96          // TODO: Fails on GitHub
97          assumeTrue(System.getenv("GITHUB_WORKFLOW") == null);
98  
99          final DefaultExecutor executor = DefaultExecutor.builder().get();
100         executor.setStreamHandler(new PumpStreamHandler(System.out, System.err, System.in));
101         executor.setWatchdog(new ExecuteWatchdog(WATCHDOG_TIMEOUT));
102         final CommandLine command = new CommandLine(resolveTestScript("issues", "exec-65"));
103 
104         assertThrows(ExecuteException.class, () -> executor.execute(command));
105     }
106 
107     @Test
108     @DisabledOnOs(org.junit.jupiter.api.condition.OS.WINDOWS)
109     @Timeout(value = TEST_TIMEOUT, unit = TimeUnit.MILLISECONDS)
110     void testExec65WitSleepUsingSleepCommandDirectly() throws Exception {
111         final ExecuteWatchdog watchdog = new ExecuteWatchdog(WATCHDOG_TIMEOUT);
112         final DefaultExecutor executor = DefaultExecutor.builder().get();
113         final CommandLine command = new CommandLine("sleep");
114         command.addArgument("60");
115         executor.setStreamHandler(new PumpStreamHandler(System.out, System.err));
116         executor.setWatchdog(watchdog);
117 
118         assertThrows(ExecuteException.class, () -> executor.execute(command));
119     }
120 }