--- /dev/null Thu May 31 14:50:37 2012 +++ new/test/java/lang/Process/ProcessKillTest.java Thu May 31 14:50:36 2012 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2012, 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.*; +import java.util.concurrent.TimeUnit; + +public class ProcessKillTest implements Runnable { + + private Process p; + private static enum OS { + WINDOWS, LINUX, SOLARIS, MAC + } + private static OS currentOS; + + public ProcessKillTest() throws Exception { + String osName = System.getProperty("os.name"); + if(osName.toLowerCase().indexOf("win") == 0) + currentOS = OS.WINDOWS; + else if(osName.toLowerCase().indexOf("lin") == 0) + currentOS = OS.LINUX; + else if(osName.contains("OS X")) + currentOS = OS.MAC; + + ProcessBuilder bldr; + if (currentOS == OS.WINDOWS) + bldr = new ProcessBuilder("ping", "-t", "127.0.0.1"); + else + bldr = new ProcessBuilder("./ProcessTrap.sh"); + bldr.redirectErrorStream(true); + bldr.directory(new File(".")); + p = bldr.start(); + } + + public Process getProc() { + return p; + } + + public void killProc(boolean force) throws Exception { + if(force) { + p.destroyForcibly().waitFor(); + // System.out.println(p.exitValue()); + if ((currentOS == OS.SOLARIS && p.exitValue() != 9) || + ((currentOS == OS.LINUX || currentOS == OS.MAC) + && p.exitValue() != 137)) + throw new RuntimeException("Test failed: wrong exit value"); + } else { + p.destroy(); + } + } + + public boolean isAlive() { + return p.isAlive(); + } + + public void run() { + try { + String line; + BufferedReader is = + new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = is.readLine()) != null) + System.err.println("ProcessTrap: " + line); + } catch(IOException e) { + if (!e.getMessage().equals("Stream closed")) { + throw new RuntimeException(e); + } + } + } + + public static void runTest(ProcessKillTest test) throws Exception { + TimeUnit nanos = TimeUnit.NANOSECONDS; + + // this tests that the script is trapping the SIGTERM properly + // and that it doesn't cause the process to terminate. + // since windows would kill the process on a destroy(false) + // we don't perform this test. + // On Mac, it appears that when we close the processes streams + // after a destroy() call, the process terminates with a + // SIGPIPE even if it was trapping the SIGTERM, so as with + // windows, we skip this trap test. + if(currentOS == OS.SOLARIS || currentOS == OS.LINUX) + test.killProc(false); + + long start = System.nanoTime(); + if (!test.isAlive() || + test.getProc().waitFor(0, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Test failed: Process exited prematurely"); + } + long end = System.nanoTime(); + if(nanos.toMillis(end - start) > 10) + throw new RuntimeException( + "Test failed: waitFor took too long"); + + start = System.nanoTime(); + test.getProc().waitFor(3000, TimeUnit.MILLISECONDS); + end = System.nanoTime(); + if(nanos.toMillis(end - start) < 3000) + throw new RuntimeException( + "Test failed: waitFor didn't take long enough"); + + if(currentOS == OS.WINDOWS) + test.killProc(false); // make sure killProc(false) works on win + else + test.killProc(true); // test destroyForcibly(true); + test.getProc().waitFor(); + + start = System.nanoTime(); + if (test.isAlive() || + !test.getProc().waitFor(0, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Test failed: Process hasn't been killed, please terminate " + + test.getProc().toString() + " manually"); + } + end = System.nanoTime(); + if(nanos.toMillis(end - start) > 10) + throw new RuntimeException( + "Test failed: waitFor took too long with a timeout of 0"); + + + start = System.nanoTime(); + test.getProc().waitFor(100, TimeUnit.MILLISECONDS); + end = System.nanoTime(); + if(nanos.toMillis(end - start) > 10) + throw new RuntimeException( + "Test failed: waitFor took too long on dead process"); + + System.out.println("Test passed"); + } + + public static void main(String args[]) throws Exception { + ProcessKillTest test = new ProcessKillTest(); + new Thread(test).start(); + Thread.sleep(1000); + runTest(test); + } +}