6943190: TEST_BUG: some tests in java/lang/Runtime/exec have hard-coded path to shell commands
authorigerasim
Mon, 24 Mar 2014 14:14:03 +0400
changeset 23569 1ef5563dedda
parent 23568 c92e1347bcac
child 23570 6b0a90ae5eaa
6943190: TEST_BUG: some tests in java/lang/Runtime/exec have hard-coded path to shell commands Reviewed-by: martin, rriggs, alanb
jdk/test/java/lang/Runtime/exec/ConcurrentRead.java
jdk/test/java/lang/Runtime/exec/ExecWithDir.java
jdk/test/java/lang/Runtime/exec/ExecWithInput.java
jdk/test/java/lang/Runtime/exec/ExitValue.java
jdk/test/java/lang/Runtime/exec/LotsOfDestroys.java
jdk/test/java/lang/Runtime/exec/LotsOfOutput.java
jdk/test/java/lang/Runtime/exec/SleepyCat.java
jdk/test/java/lang/Runtime/exec/Status.java
jdk/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java
jdk/test/java/lang/Runtime/exec/UnixCommands.java
--- a/jdk/test/java/lang/Runtime/exec/ConcurrentRead.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/ConcurrentRead.java	Mon Mar 24 14:14:03 2014 +0400
@@ -30,21 +30,19 @@
 
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.File;
-import java.io.IOException;
 
 public class ConcurrentRead {
 
     static volatile Exception savedException;
-    static final String TEE = "/usr/bin/tee";
 
     public static void main(String[] args) throws Exception {
+        if (! UnixCommands.isUnix) {
+            System.out.println("For UNIX only");
+            return;
+        }
+        UnixCommands.ensureCommandsAvailable("tee");
 
-        if (File.separatorChar == '\\' ||                // Windows
-                                !new File(TEE).exists()) // no tee
-            return;
-
-        Process p = Runtime.getRuntime().exec(TEE);
+        Process p = Runtime.getRuntime().exec(UnixCommands.tee());
         OutputStream out = p.getOutputStream();
         InputStream in = p.getInputStream();
         Thread t1 = new WriterThread(out, in);
--- a/jdk/test/java/lang/Runtime/exec/ExecWithDir.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/ExecWithDir.java	Mon Mar 24 14:14:03 2014 +0400
@@ -28,21 +28,25 @@
  *          directory is specified
  */
 
-import java.io.*;
+import java.io.File;
 
 public class ExecWithDir {
 
-    private static final String CMD = "/bin/true";
     private static final int N = 500;
 
     public static void main(String args[]) throws Exception {
-        if (! new File(CMD).canExecute())
+        if (! UnixCommands.isUnix) {
+            System.out.println("For UNIX only");
             return;
+        }
+        UnixCommands.ensureCommandsAvailable("true");
+
+        final String trueCmd = UnixCommands.findCommand("true");
         File dir = new File(".");
         for (int i = 1; i <= N; i++) {
             System.out.print(i);
             System.out.print(" e");
-            Process p = Runtime.getRuntime().exec(CMD, null, dir);
+            Process p = Runtime.getRuntime().exec(trueCmd, null, dir);
             System.out.print('w');
             int s = p.waitFor();
             System.out.println("x " + s);
--- a/jdk/test/java/lang/Runtime/exec/ExecWithInput.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/ExecWithInput.java	Mon Mar 24 14:14:03 2014 +0400
@@ -39,7 +39,6 @@
 
 public class ExecWithInput {
 
-    private static final String CAT = "/bin/cat";
     private static final int N = 200;
 
     static int go(int i) throws Exception {
@@ -50,8 +49,7 @@
          * program exits. Under 1.4.1, cat sometimes gets stuck on a pipe
          * read and never terminates.
          */
-        //Process p = Runtime.getRuntime().exec(new String[] { CAT } );
-        Process p = Runtime.getRuntime().exec(CAT);
+        Process p = Runtime.getRuntime().exec(UnixCommands.cat());
 
         String input = i + ": line 1\n" + i + ": line 2\n";
         StringBufferInputStream in = new StringBufferInputStream(input);
@@ -65,12 +63,12 @@
     }
 
     public static void main(String[] args) throws Exception {
-        if (!System.getProperty("os.name").equals("Linux"))
-            return;
-        if (File.separatorChar == '\\') {
-            // no /bin/cat on windows
+        if (! UnixCommands.isLinux) {
+            System.out.println("For Linux only");
             return;
         }
+        UnixCommands.ensureCommandsAvailable("cat");
+
         for (int i = 0; i < N; i++)
             go(i);
     }
@@ -93,7 +91,6 @@
 
         public void run() {
             try {
-                int c;
                 byte[] buf = new byte[8192];
                 int n;
                 while ((n = in.read(buf)) != -1) {
--- a/jdk/test/java/lang/Runtime/exec/ExitValue.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/ExitValue.java	Mon Mar 24 14:14:03 2014 +0400
@@ -68,13 +68,18 @@
                                                 int expectedExitValue)
         throws Exception
     {
-        checkExitValue(new String[] { "/bin/sh", "-c", posixShellProgram },
+        checkExitValue(new String[] { UnixCommands.sh(), "-c", posixShellProgram },
                        expectedExitValue);
     }
 
     final static int EXIT_CODE = 5;
 
     public static void main(String[] args) throws Exception {
+        if (! UnixCommands.isUnix) {
+            System.out.println("For UNIX only");
+            return;
+        }
+        UnixCommands.ensureCommandsAvailable("sh", "true", "kill");
 
         String java = join(File.separator, new String []
             { System.getProperty("java.home"), "bin", "java" });
@@ -85,17 +90,14 @@
               "ExitValue$Run", String.valueOf(EXIT_CODE)
             }, EXIT_CODE);
 
-        checkExitValue(new String[] { "/bin/true" }, 0);
+        checkExitValue(new String[] { UnixCommands.findCommand("true") }, 0);
 
         checkPosixShellExitValue("exit", 0);
 
         checkPosixShellExitValue("exit 7", 7);
 
-        if (new File("/bin/kill").exists()) {
-            int sigoffset =
-                System.getProperty("os.name").equals("SunOS") ? 0 : 128;
-            checkPosixShellExitValue("/bin/kill -9 $$", sigoffset+9);
-        }
+        int sigoffset = UnixCommands.isSunOS ? 0 : 128;
+        checkPosixShellExitValue(UnixCommands.kill() + " -9 $$", sigoffset+9);
     }
 
     public static class Run {
--- a/jdk/test/java/lang/Runtime/exec/LotsOfDestroys.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/LotsOfDestroys.java	Mon Mar 24 14:14:03 2014 +0400
@@ -28,19 +28,19 @@
  * @author kladko
  */
 
-import java.io.File;
-
 public class LotsOfDestroys {
     static final int RUNS = 400;
-    static final String ECHO = "/usr/bin/echo";
 
     public static void main(String[] args) throws Exception {
-        if (File.separatorChar == '\\' ||                // Windows
-                                !new File(ECHO).exists()) // no echo
+        if (! UnixCommands.isUnix) {
+            System.out.println("For UNIX only");
             return;
+        }
+        UnixCommands.ensureCommandsAvailable("echo");
 
-        for (int i = 0; i<= RUNS; i++) {
-            Process process = Runtime.getRuntime().exec(ECHO + " x");
+        for (int i = 0; i <= RUNS; i++) {
+            Process process = Runtime.getRuntime().exec(
+                    UnixCommands.echo() + " x");
             process.destroy();
         }
     }
--- a/jdk/test/java/lang/Runtime/exec/LotsOfOutput.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/LotsOfOutput.java	Mon Mar 24 14:14:03 2014 +0400
@@ -28,16 +28,16 @@
  * @author kladko
  */
 
-import java.io.File;
-
 public class LotsOfOutput {
-    static final String CAT = "/usr/bin/cat";
 
-    public static void main(String[] args) throws Exception{
-        if (File.separatorChar == '\\' ||                // Windows
-                                !new File(CAT).exists()) // no cat
+    public static void main(String[] args) throws Exception {
+        if (! UnixCommands.isUnix) {
+            System.out.println("For UNIX only");
             return;
-        Process p = Runtime.getRuntime().exec(CAT + " /dev/zero");
+        }
+        UnixCommands.ensureCommandsAvailable("cat");
+
+        Process p = Runtime.getRuntime().exec(UnixCommands.cat() + " /dev/zero");
         long initMemory = Runtime.getRuntime().totalMemory();
         for (int i=1; i< 10; i++) {
             Thread.sleep(100);
--- a/jdk/test/java/lang/Runtime/exec/SleepyCat.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/SleepyCat.java	Mon Mar 24 14:14:03 2014 +0400
@@ -73,8 +73,8 @@
         // slower, making the child more likely to win the race!
         int iterations = 20;
         int timeout = 30;
-        String[] catArgs   = new String[] {"/bin/cat"};
-        String[] sleepArgs = new String[] {"/bin/sleep",
+        String[] catArgs   = new String[] {UnixCommands.cat()};
+        String[] sleepArgs = new String[] {UnixCommands.sleep(),
                                             String.valueOf(timeout+1)};
         Process[] cats   = new Process[iterations];
         Process[] sleeps = new Process[iterations];
@@ -126,8 +126,9 @@
         timer.schedule(sleeperExecutioner, timeout * 1000);
         byte[] buffer = new byte[10];
         String[] args =
-            new String[] {"/bin/sh", "-c",
-                          "exec sleep " + (timeout+1) + " >/dev/null"};
+            new String[] {UnixCommands.sh(), "-c",
+                          "exec " + UnixCommands.sleep() + " "
+                                  + (timeout+1) + " >/dev/null"};
 
         for (int i = 0;
              i < backgroundSleepers.length && !sleeperExecutioner.timedOut();
@@ -153,12 +154,13 @@
     }
 
     public static void main (String[] args) throws Exception {
-        try {
-            if (hang1() | hang2())
-                throw new Exception("Read from closed pipe hangs");
-        } catch (IOException e) {
-            // We will get here on non-Posix systems,
-            // which don't have cat and sleep and sh.
+        if (! UnixCommands.isUnix) {
+            System.out.println("For UNIX only");
+            return;
         }
+        UnixCommands.ensureCommandsAvailable("sh", "cat", "sleep");
+
+        if (hang1() | hang2())
+            throw new Exception("Read from closed pipe hangs");
     }
 }
--- a/jdk/test/java/lang/Runtime/exec/Status.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/Status.java	Mon Mar 24 14:14:03 2014 +0400
@@ -35,10 +35,15 @@
     public static void main(String args[])
         throws Exception
     {
-        if (!System.getProperty("os.name").equals("Linux"))
+        if (!System.getProperty("os.name").equals("Linux")) {
+            System.out.println("Only for Linux");
             return;
+        }
+        UnixCommands.ensureCommandsAvailable("false");
+
+        final String falseCmd = UnixCommands.findCommand("false");
         for (int i = 0; i < N; i++) {
-            Process p = Runtime.getRuntime().exec("false");
+            Process p = Runtime.getRuntime().exec(falseCmd);
             int s = p.waitFor();
             System.out.print(s);
             System.out.print(' ');
--- a/jdk/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java	Mon Mar 24 10:40:19 2014 +0100
+++ b/jdk/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java	Mon Mar 24 14:14:03 2014 +0400
@@ -102,7 +102,7 @@
         CountDownLatch latch = new CountDownLatch(2);
 
         System.err.println("test");
-        Process p = Runtime.getRuntime().exec("/bin/cat");
+        Process p = Runtime.getRuntime().exec(UnixCommands.cat());
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
                                 false, false, latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
@@ -122,7 +122,7 @@
         CountDownLatch latch = new CountDownLatch(2);
 
         System.err.println("testCloseBeforeDestroy");
-        Process p = Runtime.getRuntime().exec("/bin/cat");
+        Process p = Runtime.getRuntime().exec(UnixCommands.cat());
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
                                 true, false, latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
@@ -143,7 +143,7 @@
     static void testCloseAfterDestroy() throws Exception {
         CountDownLatch latch = new CountDownLatch(2);
         System.err.println("testCloseAfterDestroy");
-        Process p = Runtime.getRuntime().exec("/bin/cat");
+        Process p = Runtime.getRuntime().exec(UnixCommands.cat());
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
                                 true, false,latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
@@ -165,7 +165,7 @@
     static void testInterrupt() throws Exception {
         CountDownLatch latch = new CountDownLatch(2);
         System.err.println("testInterrupt");
-        Process p = Runtime.getRuntime().exec("/bin/cat");
+        Process p = Runtime.getRuntime().exec(UnixCommands.cat());
         Copier cp1 = new Copier("out", p.getInputStream(), System.err,
                                 false, true, latch);
         Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
@@ -186,10 +186,13 @@
 
     public static void main(String[] args) throws Exception {
 
-        // Applies only to Solaris; Linux and Windows
-        // behave a little differently
-        if (!System.getProperty("os.name").equals("SunOS"))
+        // Applies only to Solaris;
+        // Linux and Windows behave a little differently
+        if (! UnixCommands.isSunOS) {
+            System.out.println("For SunOS only");
             return;
+        }
+        UnixCommands.ensureCommandsAvailable("cat");
 
         test();
         testCloseBeforeDestroy();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Runtime/exec/UnixCommands.java	Mon Mar 24 14:14:03 2014 +0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for finding the command on the current system
+ */
+public class UnixCommands {
+
+    public static final boolean isUnix = ! System.getProperty("os.name").startsWith("Windows");
+    public static final boolean isLinux = System.getProperty("os.name").startsWith("Linux");
+    public static final boolean isSunOS = System.getProperty("os.name").equals("SunOS");
+
+    private static final String[] paths = {"/bin", "/usr/bin"};
+
+    private static Map<String,String> nameToCommand = new HashMap<>(16);
+
+    /**
+     * Throws Error unless every listed command is available on the system
+     */
+    public static void ensureCommandsAvailable(String... commands) {
+        for (String command : commands) {
+            if (findCommand(command) == null) {
+                throw new Error("Command '" + command + "' not found; bailing out");
+            }
+        }
+    }
+
+    /**
+     * If the path to the command could be found, returns the command with the full path.
+     * Otherwise, returns null.
+     */
+    public static String cat()   { return findCommand("cat"); }
+    public static String sh()    { return findCommand("sh"); }
+    public static String kill()  { return findCommand("kill"); }
+    public static String sleep() { return findCommand("sleep"); }
+    public static String tee()   { return findCommand("tee"); }
+    public static String echo()  { return findCommand("echo"); }
+
+    public static String findCommand(String name) {
+        if (nameToCommand.containsKey(name)) {
+            return nameToCommand.get(name);
+        }
+        String command = findCommand0(name);
+        nameToCommand.put(name, command);
+        return command;
+    }
+
+    private static String findCommand0(String name) {
+        for (String path : paths) {
+            File file = new File(path, name);
+            if (file.canExecute()) {
+                return file.getPath();
+            }
+        }
+        return null;
+    }
+}