--- old/test/java/lang/Runtime/exec/ConcurrentRead.java 2014-03-20 11:15:16.668664927 +0400 +++ new/test/java/lang/Runtime/exec/ConcurrentRead.java 2014-03-20 11:15:15.992673425 +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 (File.separatorChar == '\\' || // Windows - !new File(TEE).exists()) // no tee + if (! UnixCommands.isUnix) { + System.out.println("For UNIX only"); return; + } + UnixCommands.ensureCommandsAvailable("tee"); - 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); --- old/test/java/lang/Runtime/exec/ExecWithDir.java 2014-03-20 11:15:18.080647176 +0400 +++ new/test/java/lang/Runtime/exec/ExecWithDir.java 2014-03-20 11:15:17.468654871 +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); --- old/test/java/lang/Runtime/exec/ExecWithInput.java 2014-03-20 11:15:19.412630431 +0400 +++ new/test/java/lang/Runtime/exec/ExecWithInput.java 2014-03-20 11:15:18.812637975 +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) { --- old/test/java/lang/Runtime/exec/ExitValue.java 2014-03-20 11:15:20.724613937 +0400 +++ new/test/java/lang/Runtime/exec/ExitValue.java 2014-03-20 11:15:20.120621530 +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 { --- old/test/java/lang/Runtime/exec/LotsOfDestroys.java 2014-03-20 11:15:22.084596840 +0400 +++ new/test/java/lang/Runtime/exec/LotsOfDestroys.java 2014-03-20 11:15:21.464604635 +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(); } } --- old/test/java/lang/Runtime/exec/LotsOfOutput.java 2014-03-20 11:15:23.456579592 +0400 +++ new/test/java/lang/Runtime/exec/LotsOfOutput.java 2014-03-20 11:15:22.784588039 +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); --- old/test/java/lang/Runtime/exec/SleepyCat.java 2014-03-20 11:15:24.912561288 +0400 +++ new/test/java/lang/Runtime/exec/SleepyCat.java 2014-03-20 11:15:24.304568931 +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"); } } --- old/test/java/lang/Runtime/exec/Status.java 2014-03-20 11:15:26.336543385 +0400 +++ new/test/java/lang/Runtime/exec/Status.java 2014-03-20 11:15:25.692551481 +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(' '); --- old/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java 2014-03-20 11:15:27.688526388 +0400 +++ new/test/java/lang/Runtime/exec/StreamsSurviveDestroy.java 2014-03-20 11:15:27.088533932 +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 2014-03-20 07:39:19.855011806 +0400 +++ new/test/java/lang/Runtime/exec/UnixCommands.java 2014-03-20 11:15:28.428517086 +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 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; + } +}