8007142: Add utility classes for writing better multiprocess tests in jtreg
authorykantser
Thu, 07 Feb 2013 11:22:04 +0100
changeset 15645 8d05e519bffb
parent 15644 2dfa520c7303
child 15646 b065aeb8e26b
8007142: Add utility classes for writing better multiprocess tests in jtreg Reviewed-by: alanb, rbackman
jdk/test/lib/testlibrary/OutputAnalyzerTest.java
jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java
jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java
jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java
jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java
jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/OutputAnalyzerTest.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+/*
+ * @test
+ * @summary Test the OutputAnalyzer utility class
+ * @library /testlibrary
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+
+public class OutputAnalyzerTest {
+
+    public static void main(String args[]) throws Exception {
+
+        String stdout = "aaaaaa";
+        String stderr = "bbbbbb";
+        String nonExistingString = "cccc";
+
+        OutputAnalyzer output = new OutputAnalyzer(stdout, stderr);
+
+        if (!stdout.equals(output.getStdout())) {
+            throw new Exception("getStdout() returned '" + output.getStdout()
+                    + "', expected '" + stdout + "'");
+        }
+
+        if (!stderr.equals(output.getStderr())) {
+            throw new Exception("getStderr() returned '" + output.getStderr()
+                    + "', expected '" + stderr + "'");
+        }
+
+        try {
+            output.shouldContain(stdout);
+            output.stdoutShouldContain(stdout);
+            output.shouldContain(stderr);
+            output.stderrShouldContain(stderr);
+        } catch (RuntimeException e) {
+            throw new Exception("shouldContain() failed", e);
+        }
+
+        try {
+            output.shouldContain(nonExistingString);
+            throw new Exception("shouldContain() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stdoutShouldContain(stderr);
+            throw new Exception(
+                    "stdoutShouldContain() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stderrShouldContain(stdout);
+            throw new Exception(
+                    "stdoutShouldContain() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.shouldNotContain(nonExistingString);
+            output.stdoutShouldNotContain(nonExistingString);
+            output.stderrShouldNotContain(nonExistingString);
+        } catch (RuntimeException e) {
+            throw new Exception("shouldNotContain() failed", e);
+        }
+
+        try {
+            output.shouldNotContain(stdout);
+            throw new Exception("shouldContain() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stdoutShouldNotContain(stdout);
+            throw new Exception("shouldContain() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stderrShouldNotContain(stderr);
+            throw new Exception("shouldContain() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        String stdoutPattern = "[a]";
+        String stderrPattern = "[b]";
+        String nonExistingPattern = "[c]";
+
+        // Should match
+        try {
+            output.shouldMatch(stdoutPattern);
+            output.stdoutShouldMatch(stdoutPattern);
+            output.shouldMatch(stderrPattern);
+            output.stderrShouldMatch(stderrPattern);
+        } catch (RuntimeException e) {
+            throw new Exception("shouldMatch() failed", e);
+        }
+
+        try {
+            output.shouldMatch(nonExistingPattern);
+            throw new Exception("shouldMatch() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stdoutShouldMatch(stderrPattern);
+            throw new Exception(
+                    "stdoutShouldMatch() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stderrShouldMatch(stdoutPattern);
+            throw new Exception(
+                    "stderrShouldMatch() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        // Should not match
+        try {
+            output.shouldNotMatch(nonExistingPattern);
+            output.stdoutShouldNotMatch(nonExistingPattern);
+            output.stderrShouldNotMatch(nonExistingPattern);
+        } catch (RuntimeException e) {
+            throw new Exception("shouldNotMatch() failed", e);
+        }
+
+        try {
+            output.shouldNotMatch(stdoutPattern);
+            throw new Exception("shouldNotMatch() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stdoutShouldNotMatch(stdoutPattern);
+            throw new Exception("shouldNotMatch() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        try {
+            output.stderrShouldNotMatch(stderrPattern);
+            throw new Exception("shouldNotMatch() failed to throw exception");
+        } catch (RuntimeException e) {
+            // expected
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.testlibrary;
+
+import java.util.ArrayList;
+
+public class JcmdBase {
+
+    private static ProcessBuilder processBuilder = new ProcessBuilder();
+
+    /**
+     * Attach jcmd to the current process
+     *
+     * @param commandArgs
+     *            jcmd command line parameters, e.g. JFR.start
+     * @return jcmd output
+     * @throws Exception
+     */
+    public final static OutputAnalyzer jcmd(String... commandArgs)
+            throws Exception {
+        ArrayList<String> cmd = new ArrayList<String>();
+        String cmdString = "";
+
+        // jcmd from the jdk to be tested
+        String jcmdPath = JdkFinder.getTool("jcmd", false);
+        cmd.add(jcmdPath);
+        cmdString += jcmdPath;
+
+        String pid = Integer.toString(ProcessTools.getProcessId());
+        cmd.add(pid);
+        cmdString += " " + pid;
+
+        for (int i = 0; i < commandArgs.length; i++) {
+            cmd.add(commandArgs[i]);
+            cmdString += " " + commandArgs[i];
+        }
+
+        // Log command line for debugging purpose
+        System.out.println("Command line:");
+        System.out.println(cmdString);
+
+        processBuilder.command(cmd);
+        OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
+
+        // Log output for debugging purpose
+        System.out.println("Command output:");
+        System.out.println(output.getOutput());
+
+        if (output.getExitValue() != 0) {
+            throw new Exception(processBuilder.command()
+                    + " resulted in exit value " + output.getExitValue()
+                    + " , expected to get 0");
+        }
+
+        return output;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.testlibrary;
+
+import java.io.File;
+
+public final class JdkFinder {
+
+    private JdkFinder() {
+    }
+
+    private static String getExecutable(String executable, String property) {
+        String binPath = System.getProperty(property);
+        if (binPath == null) {
+            throw new RuntimeException(
+                    "System property '" + property + "' not set");
+        }
+
+        binPath += File.separatorChar + "bin" + File.separatorChar + executable;
+        File toolFile = new File(binPath);
+        if (!toolFile.exists()) {
+            throw new RuntimeException(binPath + " does not exist");
+        }
+
+        return binPath;
+    }
+
+    /**
+     * Returns the full path to a java launcher in jdk/bin based on system
+     * property.
+     *
+     * @param stableJdk
+     *            see {@link #getTool(String, boolean)}
+     * @return Full path to a java launcher in jdk/bin.
+     */
+    public static String getJavaLauncher(boolean stableJdk) {
+        return getTool("java", stableJdk);
+    }
+
+    /**
+     * Returns the full path to an executable in jdk/bin based on system
+     * property. Depending on value of {@code stableJdk} the method will look for
+     * either 'compile.jdk' or 'test.jdk' system properties.
+     * 'test.jdk' is normally set by jtreg. When running test separately,
+     * set this property using '-Dtest.jdk=/path/to/jdk'.
+     *
+     * @param stableJdk
+     *            If {@code true} the {@code tool} will be retrieved
+     *            from the compile (stable) JDK.
+     *            If {@code false} the {@code tool} will be retrieved
+     *            from the test JDK.
+     * @return Full path to an executable in jdk/bin.
+     */
+    public static String getTool(String tool, boolean stableJdk) {
+        if (stableJdk) {
+            return getExecutable(tool, "compile.jdk");
+        } else {
+            return getExecutable(tool, "test.jdk");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.testlibrary;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class OutputAnalyzer {
+
+    private final String stdout;
+    private final String stderr;
+    private final int exitValue;
+
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output and exit
+     * value from a Process
+     *
+     * @param process
+     *            Process to analyze
+     * @throws IOException
+     *             If an I/O error occurs.
+     */
+    public OutputAnalyzer(Process process) throws IOException {
+        OutputBuffer output = ProcessTools.getOutput(process);
+        exitValue = process.exitValue();
+        this.stdout = output.getStdout();
+        this.stderr = output.getStderr();
+    }
+
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output
+     *
+     * @param buf
+     *            String buffer to analyze
+     */
+    public OutputAnalyzer(String buf) {
+        this(buf, buf);
+    }
+
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output
+     *
+     * @param stdout
+     *            stdout buffer to analyze
+     * @param stderr
+     *            stderr buffer to analyze
+     */
+    public OutputAnalyzer(String stdout, String stderr) {
+        this.stdout = stdout;
+        this.stderr = stderr;
+        exitValue = -1;
+    }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer contains the
+     * string
+     *
+     * @param expectedString
+     *            String that buffer should contain
+     * @throws RuntimeException
+     *             If the string was not found
+     */
+    public void shouldContain(String expectedString) {
+        if (!stdout.contains(expectedString)
+                && !stderr.contains(expectedString)) {
+            throw new RuntimeException("'" + expectedString
+                    + "' missing from stdout/stderr: [" + stdout + stderr
+                    + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout contents of output buffer contains the string
+     *
+     * @param expectedString
+     *            String that buffer should contain
+     * @throws RuntimeException
+     *             If the string was not found
+     */
+    public void stdoutShouldContain(String expectedString) {
+        if (!stdout.contains(expectedString)) {
+            throw new RuntimeException("'" + expectedString
+                    + "' missing from stdout: [" + stdout + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stderr contents of output buffer contains the string
+     *
+     * @param expectedString
+     *            String that buffer should contain
+     * @throws RuntimeException
+     *             If the string was not found
+     */
+    public void stderrShouldContain(String expectedString) {
+        if (!stderr.contains(expectedString)) {
+            throw new RuntimeException("'" + expectedString
+                    + "' missing from stderr: [" + stderr + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer does not
+     * contain the string
+     *
+     * @param expectedString
+     *            String that the buffer should not contain
+     * @throws RuntimeException
+     *             If the string was found
+     */
+    public void shouldNotContain(String notExpectedString) {
+        if (stdout.contains(notExpectedString)) {
+            throw new RuntimeException("'" + notExpectedString
+                    + "' found in stdout: [" + stdout + "]\n");
+        }
+        if (stderr.contains(notExpectedString)) {
+            throw new RuntimeException("'" + notExpectedString
+                    + "' found in stderr: [" + stderr + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout contents of output buffer does not contain the
+     * string
+     *
+     * @param expectedString
+     *            String that the buffer should not contain
+     * @throws RuntimeException
+     *             If the string was found
+     */
+    public void stdoutShouldNotContain(String notExpectedString) {
+        if (stdout.contains(notExpectedString)) {
+            throw new RuntimeException("'" + notExpectedString
+                    + "' found in stdout: [" + stdout + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stderr contents of output buffer does not contain the
+     * string
+     *
+     * @param expectedString
+     *            String that the buffer should not contain
+     * @throws RuntimeException
+     *             If the string was found
+     */
+    public void stderrShouldNotContain(String notExpectedString) {
+        if (stderr.contains(notExpectedString)) {
+            throw new RuntimeException("'" + notExpectedString
+                    + "' found in stderr: [" + stderr + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer matches
+     * the pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public void shouldMatch(String pattern) {
+        Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' missing from stdout/stderr: [" + stdout + stderr
+                    + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout contents of output buffer matches the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public void stdoutShouldMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (!matcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' missing from stdout: [" + stdout + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stderr contents of output buffer matches the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public void stderrShouldMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (!matcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' missing from stderr: [" + stderr + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer does not
+     * match the pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was found
+     */
+    public void shouldNotMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (matcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' found in stdout: [" + stdout + "]\n");
+        }
+        matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (matcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' found in stderr: [" + stderr + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stdout contents of output buffer does not match the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was found
+     */
+    public void stdoutShouldNotMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (matcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' found in stdout: [" + stdout + "]\n");
+        }
+    }
+
+    /**
+     * Verify that the stderr contents of output buffer does not match the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was found
+     */
+    public void stderrShouldNotMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (matcher.find()) {
+            throw new RuntimeException("'" + pattern
+                    + "' found in stderr: [" + stderr + "]\n");
+        }
+    }
+
+    /**
+     * Verifiy the exit value of the process
+     *
+     * @param expectedExitValue
+     *            Expected exit value from process
+     * @throws RuntimeException
+     *             If the exit value from the process did not match the expected
+     *             value
+     */
+    public void shouldHaveExitValue(int expectedExitValue) {
+        if (getExitValue() != expectedExitValue) {
+            throw new RuntimeException("Exit value " + getExitValue()
+                    + " , expected to get " + expectedExitValue);
+        }
+    }
+
+    /**
+     * Get the contents of the output buffer (stdout and stderr)
+     *
+     * @return Content of the output buffer
+     */
+    public String getOutput() {
+        return stdout + stderr;
+    }
+
+    /**
+     * Get the contents of the stdout buffer
+     *
+     * @return Content of the stdout buffer
+     */
+    public String getStdout() {
+        return stdout;
+    }
+
+    /**
+     * Get the contents of the stderr buffer
+     *
+     * @return Content of the stderr buffer
+     */
+    public String getStderr() {
+        return stderr;
+    }
+
+    /**
+     * Get the process exit value
+     *
+     * @return Process exit value
+     */
+    public int getExitValue() {
+        return exitValue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.testlibrary;
+
+public class OutputBuffer {
+    private final String stdout;
+    private final String stderr;
+
+    /**
+     * Create an OutputBuffer, a class for storing and managing stdout and
+     * stderr results separately
+     *
+     * @param stdout
+     *            stdout result
+     * @param stderr
+     *            stderr result
+     */
+    public OutputBuffer(String stdout, String stderr) {
+        this.stdout = stdout;
+        this.stderr = stderr;
+    }
+
+    /**
+     * Returns the stdout result
+     *
+     * @return stdout result
+     */
+    public String getStdout() {
+        return stdout;
+    }
+
+    /**
+     * Returns the stderr result
+     *
+     * @return stderr result
+     */
+    public String getStderr() {
+        return stderr;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.testlibrary;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import sun.management.VMManagement;
+
+public final class ProcessTools {
+
+    private ProcessTools() {
+    }
+
+    /**
+     * Pumps stdout and stderr from running the process into a String.
+     *
+     * @param processHandler
+     *            ProcessHandler to run.
+     * @return Output from process.
+     * @throws IOException
+     *             If an I/O error occurs.
+     */
+    public static OutputBuffer getOutput(ProcessBuilder processBuilder)
+            throws IOException {
+        return getOutput(processBuilder.start());
+    }
+
+    /**
+     * Pumps stdout and stderr the running process into a String.
+     *
+     * @param process
+     *            Process to pump.
+     * @return Output from process.
+     * @throws IOException
+     *             If an I/O error occurs.
+     */
+    public static OutputBuffer getOutput(Process process) throws IOException {
+        ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
+        ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
+        StreamPumper outPumper = new StreamPumper(process.getInputStream(),
+                stdoutBuffer);
+        StreamPumper errPumper = new StreamPumper(process.getErrorStream(),
+                stderrBuffer);
+        Thread outPumperThread = new Thread(outPumper);
+        Thread errPumperThread = new Thread(errPumper);
+
+        outPumperThread.setDaemon(true);
+        errPumperThread.setDaemon(true);
+
+        outPumperThread.start();
+        errPumperThread.start();
+
+        try {
+            process.waitFor();
+            outPumperThread.join();
+            errPumperThread.join();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            return null;
+        }
+
+        return new OutputBuffer(stdoutBuffer.toString(),
+                stderrBuffer.toString());
+    }
+
+    /**
+     * Get the process id of the current running Java process
+     *
+     * @return Process id
+     */
+    public static int getProcessId() throws Exception {
+
+        // Get the current process id using a reflection hack
+        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+        Field jvm = runtime.getClass().getDeclaredField("jvm");
+
+        jvm.setAccessible(true);
+        VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+
+        Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
+
+        pid_method.setAccessible(true);
+
+        int pid = (Integer) pid_method.invoke(mgmt);
+
+        return pid;
+    }
+
+    /**
+     * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
+     *
+     * @return String[] with platform specific arguments, empty if there are
+     *         none
+     */
+    public static String[] getPlatformSpecificVMArgs() {
+        String osName = System.getProperty("os.name");
+        String dataModel = System.getProperty("sun.arch.data.model");
+
+        if (osName.equals("SunOS") && dataModel.equals("64")) {
+            return new String[] { "-d64" };
+        }
+
+        return new String[] {};
+    }
+
+    /**
+     * Create ProcessBuilder using the java launcher from the jdk to be tested
+     * and with any platform specific arguments prepended
+     */
+    public static ProcessBuilder createJavaProcessBuilder(String... command)
+            throws Exception {
+        String javapath = JdkFinder.getJavaLauncher(false);
+
+        ArrayList<String> args = new ArrayList<>();
+        args.add(javapath);
+        Collections.addAll(args, getPlatformSpecificVMArgs());
+        Collections.addAll(args, command);
+
+        return new ProcessBuilder(args.toArray(new String[args.size()]));
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java	Thu Feb 07 11:22:04 2013 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.testlibrary;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+public final class StreamPumper implements Runnable {
+
+    private static final int BUF_SIZE = 256;
+
+    private final OutputStream out;
+    private final InputStream in;
+
+    /**
+     * Create a StreamPumper that reads from in and writes to out.
+     *
+     * @param in
+     *            The stream to read from.
+     * @param out
+     *            The stream to write to.
+     */
+    public StreamPumper(InputStream in, OutputStream out) {
+        this.in = in;
+        this.out = out;
+    }
+
+    /**
+     * Implements Thread.run(). Continuously read from {@code in} and write to
+     * {@code out} until {@code in} has reached end of stream. Abort on
+     * interruption. Abort on IOExceptions.
+     */
+    @Override
+    public void run() {
+        int length;
+        InputStream localIn = in;
+        OutputStream localOut = out;
+        byte[] buffer = new byte[BUF_SIZE];
+
+        try {
+            while ((length = localIn.read(buffer)) > 0 && !Thread.interrupted()) {
+                localOut.write(buffer, 0, length);
+            }
+        } catch (IOException e) {
+            // Just abort if something like this happens.
+            e.printStackTrace();
+        } finally {
+            try {
+                localOut.flush();
+                in.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}