6461635: [TESTBUG] BasicTests.sh test fails intermittently
Summary: Transform dummy class instead of BigInteger to avoid complication by -Xshare. Ported from script to java.
Reviewed-by: alanb
Contributed-by: mattias.tobiasson@oracle.com
--- a/jdk/test/ProblemList.txt Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/ProblemList.txt Tue Dec 03 17:06:23 2013 +0100
@@ -266,9 +266,6 @@
# jdk_tools
-# 6461635
-com/sun/tools/attach/BasicTests.sh generic-all
-
# 7132203
sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
--- a/jdk/test/com/sun/tools/attach/AgentSetup.sh Tue Dec 03 23:09:17 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 2006, 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.
-#
-
-
-#
-#
-# Agent set - creates Agent.jar, BadAgent.jar and RedefineAgent.jar in ${TESTCLASSES}
-
-$JAVAC -d "${TESTCLASSES}" "${TESTSRC}"/Agent.java "${TESTSRC}"/BadAgent.java "${TESTSRC}"/RedefineAgent.java
-
-$JAR -cfm "${TESTCLASSES}"/Agent.jar "${TESTSRC}"/agent.mf \
- -C "${TESTCLASSES}" Agent.class
-
-$JAR -cfm "${TESTCLASSES}"/BadAgent.jar "${TESTSRC}"/badagent.mf \
- -C "${TESTCLASSES}" BadAgent.class
-
-$JAR -cfm "${TESTCLASSES}"/RedefineAgent.jar "${TESTSRC}"/redefineagent.mf \
- -C "${TESTCLASSES}" RedefineAgent.class
-
-agent="${TESTCLASSES}${FS}Agent.jar"
-badagent="${TESTCLASSES}${FS}BadAgent.jar"
-redefineagent="${TESTCLASSES}${FS}RedefineAgent.jar"
-
--- a/jdk/test/com/sun/tools/attach/Application.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/com/sun/tools/attach/Application.java Tue Dec 03 17:06:23 2013 +0100
@@ -22,25 +22,39 @@
*/
/*
- *
- *
* A simple "Application" used by the Attach API unit tests. This application is
* launched by the test. It binds to a random port and shuts down when somebody
* connects to that port.
+ * Used port and pid are written both to stdout and to a specified file.
*/
import java.net.Socket;
import java.net.ServerSocket;
+import java.io.PrintWriter;
+import jdk.testlibrary.ProcessTools;
public class Application {
public static void main(String args[]) throws Exception {
// bind to a random port
+ if (args.length < 1) {
+ System.err.println("First argument should be path to output file.");
+ }
+ String outFileName = args[0];
+
ServerSocket ss = new ServerSocket(0);
int port = ss.getLocalPort();
+ int pid = ProcessTools.getProcessId();
- // signal test that we are started - do not remove this line!!
- System.out.println(port);
+ System.out.println("shutdownPort=" + port);
+ System.out.println("pid=" + pid);
System.out.flush();
+ try (PrintWriter writer = new PrintWriter(outFileName)) {
+ writer.println("shutdownPort=" + port);
+ writer.println("pid=" + pid);
+ writer.println("done");
+ writer.flush();
+ }
+
// wait for test harness to connect
Socket s = ss.accept();
s.close();
--- a/jdk/test/com/sun/tools/attach/ApplicationSetup.sh Tue Dec 03 23:09:17 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 2011, 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.
-#
-
-
-#
-#
-# Application Setup - creates ${TESTCLASSES}/Application.jar and the following
-# procedures:
-# startApplication - starts target application
-# stopApplication $1 - stops application via TCP shutdown port $1
-
-$JAVAC -d "${TESTCLASSES}" "${TESTSRC}"/Application.java "${TESTSRC}"/Shutdown.java
-$JAR -cfm "${TESTCLASSES}"/Application.jar "${TESTSRC}"/application.mf \
- -C "${TESTCLASSES}" Application.class
-
-OUTPUTFILE=${TESTCLASSES}/Application.out
-rm -f ${OUTPUTFILE}
-
-startApplication()
-{
- # put all output from the app into ${OUTPUTFILE}
- ${JAVA} ${TESTVMOPTS} $1 $2 $3 -jar "${TESTCLASSES}"/Application.jar > ${OUTPUTFILE} 2>&1 &
- pid="$!"
-
- # MKS creates an intermediate shell to launch ${JAVA} so
- # ${pid} is not the actual pid. We have put in a small sleep
- # to give the intermediate shell process time to launch the
- # "java" process.
- if [ "$OS" = "Windows" ]; then
- sleep 2
- if [ "${isCygwin}" = "true" ] ; then
- realpid=`ps -p ${pid} | tail -1 | awk '{print $4;}'`
- else
- realpid=`ps -o pid,ppid,comm|grep ${pid}|grep "java"|cut -c1-6`
- fi
- pid=${realpid}
- fi
-
- echo "Waiting for Application to initialize..."
- attempts=0
- while true; do
- sleep 1
- port=`tail -1 ${OUTPUTFILE} | sed -e 's@\\r@@g' `
- if [ ! -z "$port" ]; then
- # In case of errors wait time for output to be flushed
- sleep 1
- cat ${OUTPUTFILE}
- break
- fi
- attempts=`expr $attempts + 1`
- echo "Waiting $attempts second(s) ..."
- done
- echo "Application is process $pid, shutdown port is $port"
- return $port
-}
-
-stopApplication()
-{
- $JAVA ${TESTVMOPTS} -classpath "${TESTCLASSES}" Shutdown $1
-}
-
--- a/jdk/test/com/sun/tools/attach/BasicTests.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/com/sun/tools/attach/BasicTests.java Tue Dec 03 17:06:23 2013 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -21,160 +21,257 @@
* questions.
*/
-/*
- *
- *
- * Unit test for Attach API. Attaches to the given VM and performs a number
- * unit tests.
- */
import com.sun.tools.attach.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.Properties;
import java.util.List;
+import java.io.File;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.ProcessThread;
+/*
+ * @test
+ * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757
+ * @summary Basic unit tests for the VM attach mechanism.
+ * @library /lib/testlibrary
+ * @run build Agent BadAgent RedefineAgent Application Shutdown RedefineDummy
+ * @run main BasicTests
+ *
+ * This test will perform a number of basic attach tests.
+ */
public class BasicTests {
- public static void main(String args[]) throws Exception {
- String pid = args[0];
- String agent = args[1];
- String badagent = args[2];
- String redefineagent = args[3];
- System.out.println(" - Attaching to application ...");
- VirtualMachine vm = VirtualMachine.attach(pid);
+ /*
+ * The actual test is in the nested class TestMain.
+ * The responsibility of this class is to:
+ * 1. Build all needed jars.
+ * 2. Start the Application class in a separate process.
+ * 3. Find the pid and shutdown port of the running Application.
+ * 4. Launches the tests in nested class TestMain that will attach to the Application.
+ * 5. Shut down the Application.
+ */
+ public static void main(String args[]) throws Throwable {
+ final String pidFile = "TestsBasic.Application.pid";
+ ProcessThread processThread = null;
+ RunnerUtil.ProcessInfo info = null;
+ try {
+ buildJars();
+ processThread = RunnerUtil.startApplication(pidFile);
+ info = RunnerUtil.readProcessInfo(pidFile);
+ runTests(info.pid);
+ } catch (Throwable t) {
+ System.out.println("TestBasic got unexpected exception: " + t);
+ t.printStackTrace();
+ throw t;
+ } finally {
+ // Make sure the Application process is stopped.
+ RunnerUtil.stopApplication(info.shutdownPort, processThread);
+ }
+ }
- // Test 1 - read the system properties from the target VM and
- // check that property is set
- System.out.println(" - Test: system properties in target VM");
- Properties props = vm.getSystemProperties();
- String value = props.getProperty("attach.test");
- if (value == null || !value.equals("true")) {
- throw new RuntimeException("attach.test property not set");
- }
- System.out.println(" - attach.test property set as expected");
+ /**
+ * Runs the actual tests in nested class TestMain.
+ * The reason for running the tests in a separate process
+ * is that we need to modify the class path.
+ */
+ private static void runTests(int pid) throws Throwable {
+ final String sep = File.separator;
- // Test 1a - read the agent properties from the target VM.
- // By default, the agent property contains "sun.java.command",
- // "sun.jvm.flags", and "sun.jvm.args".
- // Just sanity check - make sure not empty.
- System.out.println(" - Test: agent properties in target VM");
- props = vm.getAgentProperties();
- if (props == null || props.size() == 0) {
- throw new RuntimeException("Agent properties is empty");
- }
- System.out.println(" - agent properties non-empty as expected");
+ // Need to add jdk/lib/tools.jar to classpath.
+ String classpath =
+ System.getProperty("test.class.path", "") + File.pathSeparator +
+ System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar";
+ String testClassDir = System.getProperty("test.classes", "") + sep;
+
+ // Argumenta : -classpath cp BasicTests$TestMain pid agent badagent redefineagent
+ String[] args = {
+ "-classpath",
+ classpath,
+ "BasicTests$TestMain",
+ Integer.toString(pid),
+ testClassDir + "Agent.jar",
+ testClassDir + "BadAgent.jar",
+ testClassDir + "RedefineAgent.jar" };
+ OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+ }
- // Test 2 - attempt to load an agent that does not exist
- System.out.println(" - Test: Load an agent that does not exist");
- try {
- vm.loadAgent("SilverBullet.jar");
- } catch (AgentLoadException x) {
- System.out.println(" - AgentLoadException thrown as expected!");
+ /**
+ * Will build all jars needed by the tests.
+ */
+ private static void buildJars() throws Throwable {
+ String[] jars = {"Agent", "BadAgent", "RedefineAgent", "Application" };
+ for (String jar : jars) {
+ buildJar(jar);
}
+ }
- // Test 3 - load an "bad" agent (agentmain throws an exception)
- System.out.println(" - Test: Load a bad agent");
- System.out.println("INFO: This test will cause error messages "
- + "to appear in the application log about SilverBullet.jar "
- + "not being found and an agent failing to start.");
- try {
- vm.loadAgent(badagent);
- throw new RuntimeException(
- "AgentInitializationException not thrown as expected!");
- } catch (AgentInitializationException x) {
- System.out.println(
- " - AgentInitializationException thrown as expected!");
- }
+ /**
+ * Will build a jar with the given name.
+ * Class file and manifest must already exist.
+ * @param jarName Name of the jar.
+ */
+ private static void buildJar(String jarName) throws Throwable {
+ String testClasses = System.getProperty("test.classes", "?");
+ String testSrc = System.getProperty("test.src", "?");
+ String jar = String.format("%s/%s.jar", testClasses, jarName);
+ String manifest = String.format("%s/%s.mf", testSrc, jarName.toLowerCase());
+ String clazz = String.format("%s.class", jarName);
+
+ // Arguments to the jar command has this format:
+ // "-cfm TESTCLASSES/Agent.jar TESTSRC/agent.mf -C TESTCLASSES Agent.class"
+ RunnerUtil.createJar("-cfm", jar, manifest, "-C", testClasses, clazz);
+ }
+
+ /**
+ * This is the actual test. It will attach to the running Application
+ * and perform a number of basic attach tests.
+ */
+ public static class TestMain {
+ public static void main(String args[]) throws Exception {
+ String pid = args[0];
+ String agent = args[1];
+ String badagent = args[2];
+ String redefineagent = args[3];
- // Test 4 - detach from the VM and attempt a load (should throw IOE)
- System.out.println(" - Test: Detach from VM");
- System.out.println("INFO: This test will cause error messages "
- + "to appear in the application log about a BadAgent including "
- + "a RuntimeException and an InvocationTargetException.");
- vm.detach();
- try {
- vm.loadAgent(agent);
- throw new RuntimeException("loadAgent did not throw an exception!!");
- } catch (IOException ioe) {
- System.out.println(" - IOException as expected");
- }
+ System.out.println(" - Attaching to application ...");
+ VirtualMachine vm = VirtualMachine.attach(pid);
+
+ // Test 1 - read the system properties from the target VM and
+ // check that property is set
+ System.out.println(" - Test: system properties in target VM");
+ Properties props = vm.getSystemProperties();
+ String value = props.getProperty("attach.test");
+ if (value == null || !value.equals("true")) {
+ throw new RuntimeException("attach.test property not set");
+ }
+ System.out.println(" - attach.test property set as expected");
- // Test 5 - functional "end-to-end" test.
- // Create a listener socket. Load Agent.jar into the target VM passing
- // it the port number of our listener. When agent loads it should connect
- // back to the tool.
-
- System.out.println(" - Re-attaching to application ...");
- vm = VirtualMachine.attach(pid);
+ // Test 1a - read the agent properties from the target VM.
+ // By default, the agent property contains "sun.java.command",
+ // "sun.jvm.flags", and "sun.jvm.args".
+ // Just sanity check - make sure not empty.
+ System.out.println(" - Test: agent properties in target VM");
+ props = vm.getAgentProperties();
+ if (props == null || props.size() == 0) {
+ throw new RuntimeException("Agent properties is empty");
+ }
+ System.out.println(" - agent properties non-empty as expected");
- System.out.println(" - Test: End-to-end connection with agent");
+ // Test 2 - attempt to load an agent that does not exist
+ System.out.println(" - Test: Load an agent that does not exist");
+ try {
+ vm.loadAgent("SilverBullet.jar");
+ } catch (AgentLoadException x) {
+ System.out.println(" - AgentLoadException thrown as expected!");
+ }
- ServerSocket ss = new ServerSocket(0);
- int port = ss.getLocalPort();
-
- System.out.println(" - Loading Agent.jar into target VM ...");
- vm.loadAgent(agent, Integer.toString(port));
+ // Test 3 - load an "bad" agent (agentmain throws an exception)
+ System.out.println(" - Test: Load a bad agent");
+ System.out.println("INFO: This test will cause error messages "
+ + "to appear in the application log about SilverBullet.jar "
+ + "not being found and an agent failing to start.");
+ try {
+ vm.loadAgent(badagent);
+ throw new RuntimeException(
+ "AgentInitializationException not thrown as expected!");
+ } catch (AgentInitializationException x) {
+ System.out.println(
+ " - AgentInitializationException thrown as expected!");
+ }
- System.out.println(" - Waiting for agent to connect back to tool ...");
- Socket s = ss.accept();
- System.out.println(" - Connected to agent.");
-
- // Test 5b - functional "end-to-end" test.
- // Now with an agent that does redefine.
+ // Test 4 - detach from the VM and attempt a load (should throw IOE)
+ System.out.println(" - Test: Detach from VM");
+ System.out.println("INFO: This test will cause error messages "
+ + "to appear in the application log about a BadAgent including "
+ + "a RuntimeException and an InvocationTargetException.");
+ vm.detach();
+ try {
+ vm.loadAgent(agent);
+ throw new RuntimeException("loadAgent did not throw an exception!!");
+ } catch (IOException ioe) {
+ System.out.println(" - IOException as expected");
+ }
- System.out.println(" - Re-attaching to application ...");
- vm = VirtualMachine.attach(pid);
+ // Test 5 - functional "end-to-end" test.
+ // Create a listener socket. Load Agent.jar into the target VM passing
+ // it the port number of our listener. When agent loads it should connect
+ // back to the tool.
+
+ System.out.println(" - Re-attaching to application ...");
+ vm = VirtualMachine.attach(pid);
+
+ System.out.println(" - Test: End-to-end connection with agent");
- System.out.println(" - Test: End-to-end connection with RedefineAgent");
+ ServerSocket ss = new ServerSocket(0);
+ int port = ss.getLocalPort();
- ServerSocket ss2 = new ServerSocket(0);
- int port2 = ss2.getLocalPort();
+ System.out.println(" - Loading Agent.jar into target VM ...");
+ vm.loadAgent(agent, Integer.toString(port));
+
+ System.out.println(" - Waiting for agent to connect back to tool ...");
+ Socket s = ss.accept();
+ System.out.println(" - Connected to agent.");
- System.out.println(" - Loading RedefineAgent.jar into target VM ...");
- vm.loadAgent(redefineagent, Integer.toString(port2));
+ // Test 5b - functional "end-to-end" test.
+ // Now with an agent that does redefine.
+
+ System.out.println(" - Re-attaching to application ...");
+ vm = VirtualMachine.attach(pid);
- System.out.println(" - Waiting for RedefineAgent to connect back to tool ...");
- Socket s2 = ss2.accept();
- System.out.println(" - Connected to RedefineAgent.");
+ System.out.println(" - Test: End-to-end connection with RedefineAgent");
+
+ ServerSocket ss2 = new ServerSocket(0);
+ int port2 = ss2.getLocalPort();
+
+ System.out.println(" - Loading RedefineAgent.jar into target VM ...");
+ vm.loadAgent(redefineagent, Integer.toString(port2));
- // Test 6 - list method should list the target VM
- System.out.println(" - Test: VirtualMachine.list");
- List<VirtualMachineDescriptor> l = VirtualMachine.list();
- if (!l.isEmpty()) {
- boolean found = false;
- for (VirtualMachineDescriptor vmd: l) {
- if (vmd.id().equals(pid)) {
- found = true;
- break;
+ System.out.println(" - Waiting for RedefineAgent to connect back to tool ...");
+ Socket s2 = ss2.accept();
+ System.out.println(" - Connected to RedefineAgent.");
+
+ // Test 6 - list method should list the target VM
+ System.out.println(" - Test: VirtualMachine.list");
+ List<VirtualMachineDescriptor> l = VirtualMachine.list();
+ if (!l.isEmpty()) {
+ boolean found = false;
+ for (VirtualMachineDescriptor vmd: l) {
+ if (vmd.id().equals(pid)) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ System.out.println(" - " + pid + " found.");
+ } else {
+ throw new RuntimeException(pid + " not found in VM list");
}
}
- if (found) {
- System.out.println(" - " + pid + " found.");
- } else {
- throw new RuntimeException(pid + " not found in VM list");
- }
- }
- // test 7 - basic hashCode/equals tests
- System.out.println(" - Test: hashCode/equals");
+ // test 7 - basic hashCode/equals tests
+ System.out.println(" - Test: hashCode/equals");
- VirtualMachine vm1 = VirtualMachine.attach(pid);
- VirtualMachine vm2 = VirtualMachine.attach(pid);
- if (!vm1.equals(vm2)) {
- throw new RuntimeException("virtual machines are not equal");
- }
- if (vm.hashCode() != vm.hashCode()) {
- throw new RuntimeException("virtual machine hashCodes not equal");
+ VirtualMachine vm1 = VirtualMachine.attach(pid);
+ VirtualMachine vm2 = VirtualMachine.attach(pid);
+ if (!vm1.equals(vm2)) {
+ throw new RuntimeException("virtual machines are not equal");
+ }
+ if (vm.hashCode() != vm.hashCode()) {
+ throw new RuntimeException("virtual machine hashCodes not equal");
+ }
+ System.out.println(" - hashCode/equals okay");
+
+ // ---
+ System.out.println(" - Cleaning up...");
+ s.close();
+ ss.close();
+ s2.close();
+ ss2.close();
}
- System.out.println(" - hashCode/equals okay");
-
-
- // ---
- System.out.println(" - Cleaning up...");
- s.close();
- ss.close();
- s2.close();
- ss2.close();
}
}
--- a/jdk/test/com/sun/tools/attach/BasicTests.sh Tue Dec 03 23:09:17 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 2011, 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
-# @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757
-# @summary Basic unit tests for the VM attach mechanism.
-#
-# @build BasicTests
-# @run shell BasicTests.sh
-
-if [ "${TESTSRC}" = "" ]
-then
- echo "TESTSRC not set. Test cannot execute. Failed."
- exit 1
-fi
-
-# Windows 2000 is a problem here, so we skip it, see 6962615
-osrev=`uname -a`
-if [ "`echo ${osrev} | grep 'CYGWIN[^ ]*-5\.0'`" != "" ] ; then
- echo "Treating as a pass, not testing Windows 2000"
- exit 0
-fi
-if [ "`echo ${osrev} | grep 'Windows'`" != "" ] ; then
- if [ "`echo ${osrev} | grep '5 00'`" != "" ] ; then
- echo "Treating as a pass, not testing Windows 2000"
- exit 0
- fi
-fi
-
-. ${TESTSRC}/CommonSetup.sh
-. ${TESTSRC}/ApplicationSetup.sh
-. ${TESTSRC}/AgentSetup.sh
-
-startApplication -Dattach.test=true
-# pid = process-id, port = shutdown port
-
-failures=0
-
-echo "Running tests ..."
-
-$JAVA ${TESTVMOPTS} -classpath "${TESTCLASSES}${PS}${TESTJAVA}/lib/tools.jar" \
- BasicTests $pid $agent $badagent $redefineagent 2>&1
-if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
-
-stopApplication $port
-
-# Add these info messages to $OUTPUTFILE just in case someone
-# looks at it and wonders about the failures. We have to do
-# this after the application is stopped because it is writing
-# to $OUTPUTFILE.
-(
-echo ""
-echo "INFO: Test 2 will cause error messages about SilverBullet.jar" \
- "and an agent failing to start."
-echo "INFO: Test 3 will cause error messages about BadAgent" \
- "including a RuntimeException and an InvocationTargetException."
-) >> ${OUTPUTFILE}
-
-if [ $failures = 0 ];
- then echo "All tests passed.";
- else echo "$failures test(s) failed:"; cat ${OUTPUTFILE};
-fi
-exit $failures
--- a/jdk/test/com/sun/tools/attach/CommonSetup.sh Tue Dec 03 23:09:17 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 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.
-#
-
-
-#
-#
-# Common setup for the Attach API unit tests. Setups up the following variables:
-#
-# PS - path sep.
-# FS - file sep.
-# JAVA - java cmd.
-# JAVAC - javac cmd.
-# JAR - jar cmd.
-
-OS=`uname -s`
-case "$OS" in
- SunOS | Linux | Darwin )
- PS=":"
- FS="/"
- ;;
- Windows* )
- PS=";"
- OS="Windows"
- FS="\\"
- ;;
- CYGWIN* )
- PS=";"
- OS="Windows"
- FS="\\"
- isCygwin=true
- ;;
- * )
- echo "Unrecognized system!"
- exit 1;
- ;;
-esac
-
-if [ "${TESTJAVA}" = "" ]
-then
- echo "TESTJAVA not set. Test cannot execute. Failed."
- exit 1
-fi
-
-if [ "${TESTSRC}" = "" ]
-then
- echo "TESTSRC not set. Test cannot execute. Failed."
- exit 1
-fi
-
-if [ "${TESTCLASSES}" = "" ]
-then
- echo "TESTCLASSES not set. Test cannot execute. Failed."
- exit 1
-fi
-
-JAVA="${TESTJAVA}/bin/java"
-JAVAC="${TESTJAVA}/bin/javac"
-JAR="${TESTJAVA}/bin/jar"
-
--- a/jdk/test/com/sun/tools/attach/PermissionTest.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/com/sun/tools/attach/PermissionTest.java Tue Dec 03 17:06:23 2013 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -21,39 +21,119 @@
* questions.
*/
-/*
- *
- *
- * Unit test for Attach API - this checks that a SecurityException is thrown as
- * expected.
- */
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AttachNotSupportedException;
import java.util.Properties;
+import java.io.File;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.ProcessThread;
+/*
+ * @test
+ * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757
+ * @summary Basic unit tests for the VM attach mechanism.
+ * @library /lib/testlibrary
+ * @run build Application Shutdown
+ * @run main PermissionTest
+ *
+ * Unit test for Attach API -
+ * this checks that a SecurityException is thrown as expected.
+ */
public class PermissionTest {
- public static void main(String args[]) throws Exception {
- SecurityManager sm = System.getSecurityManager();
- if (sm == null) {
- throw new RuntimeException("Test configuration error - no security manager set");
- }
- String pid = args[0];
- boolean shouldFail = Boolean.parseBoolean(args[1]);
-
+ /*
+ * The actual test is in the nested class TestMain.
+ * The responsibility of this class is to:
+ * 1. Start the Application class in a separate process.
+ * 2. Find the pid and shutdown port of the running Application.
+ * 3. Run the tests in TstMain that will attach to the Application.
+ * 4. Shut down the Application.
+ */
+ public static void main(String args[]) throws Throwable {
+ final String pidFile ="TestPermission.Application.pid";
+ ProcessThread processThread = null;
+ RunnerUtil.ProcessInfo info = null;
try {
- VirtualMachine.attach(pid).detach();
- if (shouldFail) {
- throw new RuntimeException("SecurityException should be thrown");
+ processThread = RunnerUtil.startApplication(pidFile);
+ info = RunnerUtil.readProcessInfo(pidFile);
+ runTests(info.pid);
+ } catch (Throwable t) {
+ System.out.println("TestPermission got unexpected exception: " + t);
+ t.printStackTrace();
+ throw t;
+ } finally {
+ // Make sure the Application process is stopped.
+ RunnerUtil.stopApplication(info.shutdownPort, processThread);
+ }
+ }
+
+ /**
+ * Runs the actual test the nested class TestMain.
+ * The test is run in a separate process because we need to add to the classpath.
+ */
+ private static void runTests(int pid) throws Throwable {
+ final String sep = File.separator;
+
+ // Need to add jdk/lib/tools.jar to classpath.
+ String classpath =
+ System.getProperty("test.class.path", "") + File.pathSeparator +
+ System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar";
+ String testSrc = System.getProperty("test.src", "") + sep;
+
+ // Use a policy that will NOT allow attach. Test will verify exception.
+ String[] args = {
+ "-classpath",
+ classpath,
+ "-Djava.security.manager",
+ String.format("-Djava.security.policy=%sjava.policy.deny", testSrc),
+ "PermissionTest$TestMain",
+ Integer.toString(pid),
+ "true" };
+ OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+
+ // Use a policy that will allow attach.
+ args = new String[] {
+ "-classpath",
+ classpath,
+ "-Djava.security.manager",
+ String.format("-Djava.security.policy=%sjava.policy.allow", testSrc),
+ "PermissionTest$TestMain",
+ Integer.toString(pid),
+ "false" };
+ output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+ }
+
+ /**
+ * This is the actual test code. It will attach to the Application and verify
+ * that we get a SecurityException when that is expected.
+ */
+ public static class TestMain {
+ public static void main(String args[]) throws Exception {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ throw new RuntimeException("Test configuration error - no security manager set");
}
- System.out.println(" - attached to target VM as expected.");
- } catch (Exception x) {
- // AttachNotSupportedException thrown when no providers can be loaded
- if (shouldFail && ((x instanceof AttachNotSupportedException) ||
- (x instanceof SecurityException))) {
- System.out.println(" - exception thrown as expected.");
- } else {
- throw x;
+
+ String pid = args[0];
+ boolean shouldFail = Boolean.parseBoolean(args[1]);
+
+ try {
+ VirtualMachine.attach(pid).detach();
+ if (shouldFail) {
+ throw new RuntimeException("SecurityException should be thrown");
+ }
+ System.out.println(" - attached to target VM as expected.");
+ } catch (Exception x) {
+ // AttachNotSupportedException thrown when no providers can be loaded
+ if (shouldFail && ((x instanceof AttachNotSupportedException) ||
+ (x instanceof SecurityException))) {
+ System.out.println(" - exception thrown as expected.");
+ } else {
+ throw x;
+ }
}
}
}
--- a/jdk/test/com/sun/tools/attach/PermissionTests.sh Tue Dec 03 23:09:17 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 2010, 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
-# @bug 6173612
-# @summary Security manager and permission tests for Attach API
-#
-# @build PermissionTest
-# @run shell PermissionTests.sh
-
-if [ "${TESTSRC}" = "" ]
-then
- echo "TESTSRC not set. Test cannot execute. Failed."
- exit 1
-fi
-
-. ${TESTSRC}/CommonSetup.sh
-. ${TESTSRC}/ApplicationSetup.sh
-
-failures=0
-
-# Start target VM
-startApplication
-# pid = process-id, port = shutdown port
-
-echo "Deny test"
-# deny
-$JAVA ${TESTVMOPTS} -classpath "${TESTCLASSES}${PS}${TESTJAVA}/lib/tools.jar" \
- -Djava.security.manager \
- -Djava.security.policy=${TESTSRC}/java.policy.deny \
- PermissionTest $pid true 2>&1
-if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
-
-# allow
-echo "Allow test"
-$JAVA ${TESTVMOPTS} -classpath "${TESTCLASSES}${PS}${TESTJAVA}/lib/tools.jar" \
- -Djava.security.manager \
- -Djava.security.policy=${TESTSRC}/java.policy.allow \
- PermissionTest $pid false 2>&1
-if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
-
-# Stop target VM
-stopApplication $port
-
-if [ $failures = 0 ];
- then echo "All tests passed.";
- else echo "$failures test(s) failed:"; cat ${OUTPUTFILE};
-fi
-exit $failures
--- a/jdk/test/com/sun/tools/attach/ProviderTest.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/com/sun/tools/attach/ProviderTest.java Tue Dec 03 17:06:23 2013 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -21,24 +21,98 @@
* questions.
*/
-/*
- *
- *
- * Unit test for Attach API. Attaches to the given VM and performs a number
- * unit tests.
- */
+import java.io.File;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.ProcessTools;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.spi.AttachProvider;
+/*
+ * @test
+ * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757
+ * @summary Basic unit tests for the VM attach mechanism.
+ * @library /lib/testlibrary
+ * @run build SimpleProvider
+ * @run main ProviderTest
+ *
+ * The test will attach and detach to/from the running Application.
+ */
public class ProviderTest {
- public static void main(String args[]) throws Exception {
- // deal with internal builds where classes are loaded from the
- // 'classes' directory rather than rt.jar
- ClassLoader cl = AttachProvider.class.getClassLoader();
- if (cl != ClassLoader.getSystemClassLoader()) {
- System.out.println("Attach API not loaded by system class loader - test skipped");
- return;
+
+ /*
+ * The actual tests are in the nested class TestMain below.
+ * The responsibility of this class is to:
+ * 1. Build the needed jar.
+ * 2. Run tests in ProviderTest.TestMain.
+ */
+ public static void main(String args[]) throws Throwable {
+ try {
+ buildJar();
+ runTests();
+ } catch (Throwable t) {
+ System.out.println("TestProvider got unexpected exception: " + t);
+ t.printStackTrace();
+ throw t;
}
- VirtualMachine.attach("simple:1234").detach();
+ }
+
+ /**
+ * Runs the actual tests in the nested class TestMain.
+ * We need to run the tests in a separate process,
+ * because we need to add to the classpath.
+ */
+ private static void runTests() throws Throwable {
+ final String sep = File.separator;
+ String testClassPath = System.getProperty("test.class.path", "");
+ String testClasses = System.getProperty("test.classes", "") + sep;
+ String jdkLib = System.getProperty("test.jdk", ".") + sep + "lib" + sep;
+
+ // Need to add SimpleProvider.jar and tools.jar to classpath.
+ String classpath =
+ testClassPath + File.pathSeparator +
+ testClasses + "SimpleProvider.jar" + File.pathSeparator +
+ jdkLib + "tools.jar";
+
+ String[] args = {
+ "-classpath",
+ classpath,
+ "ProviderTest$TestMain" };
+ OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+ }
+
+ /**
+ * Will build the SimpleProvider.jar.
+ */
+ private static void buildJar() throws Throwable {
+ final String sep = File.separator;
+ String testClasses = System.getProperty("test.classes", "?") + sep;
+ String testSrc = System.getProperty("test.src", "?") + sep;
+ String serviceDir = "META-INF" + sep + "services" + sep;
+
+ RunnerUtil.createJar(
+ "-cf", testClasses + "SimpleProvider.jar",
+ "-C", testClasses, "SimpleProvider.class",
+ "-C", testClasses, "SimpleVirtualMachine.class",
+ "-C", testSrc,
+ serviceDir + "com.sun.tools.attach.spi.AttachProvider");
+ }
+
+ /**
+ * This is the actual test code that attaches to the running Application.
+ * This class is run in a separate process.
+ */
+ public static class TestMain {
+ public static void main(String args[]) throws Exception {
+ // deal with internal builds where classes are loaded from the
+ // 'classes' directory rather than rt.jar
+ ClassLoader cl = AttachProvider.class.getClassLoader();
+ if (cl != ClassLoader.getSystemClassLoader()) {
+ System.out.println("Attach API not loaded by system class loader - test skipped");
+ return;
+ }
+ VirtualMachine.attach("simple:1234").detach();
+ }
}
}
--- a/jdk/test/com/sun/tools/attach/ProviderTests.sh Tue Dec 03 23:09:17 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#
-# Copyright (c) 2005, 2010, 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
-# @bug 6173612
-# @summary AttachProvider unit tests
-#
-# @build ProviderTest SimpleProvider
-# @run shell ProviderTests.sh
-
-if [ "${TESTSRC}" = "" ]
-then
- echo "TESTSRC not set. Test cannot execute. Failed."
- exit 1
-fi
-
-. ${TESTSRC}/CommonSetup.sh
-
-echo "Creating JAR file ..."
-
-$JAR -cf ${TESTCLASSES}/SimpleProvider.jar \
- -C ${TESTCLASSES} SimpleProvider.class \
- -C ${TESTCLASSES} SimpleVirtualMachine.class \
- -C "${TESTSRC}" META-INF/services/com.sun.tools.attach.spi.AttachProvider
-
-echo "Running test ..."
-
-$JAVA ${TESTVMOPTS} -classpath \
- "${TESTCLASSES}${PS}${TESTCLASSES}/SimpleProvider.jar${PS}${TESTJAVA}/lib/tools.jar" \
- ProviderTest
-
--- a/jdk/test/com/sun/tools/attach/RedefineAgent.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/com/sun/tools/attach/RedefineAgent.java Tue Dec 03 17:06:23 2013 +0100
@@ -43,15 +43,15 @@
public class RedefineAgent implements ClassFileTransformer {
static byte[] classfilebytes;
- static final String targetName = "java.math.BigInteger";
- static final String targetNameSlashes = "java/math/BigInteger";
+ static final String targetName = "RedefineDummy";
+ static final String targetNameSlashes = "RedefineDummy";
static boolean gotRedefineTransform = false;
// test transform and capture class bytes for redefine
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
+ ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
if (className.equals(targetNameSlashes)) {
if (classBeingRedefined == null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/RedefineDummy.java Tue Dec 03 17:06:23 2013 +0100
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/*
+ * Simple dummy class used to test class retransform.
+ */
+public class RedefineDummy {
+ public String toString() {
+ return "RedefineDummy";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/RunnerUtil.java Tue Dec 03 17:06:23 2013 +0100
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.Utils;
+import jdk.testlibrary.ProcessThread;
+
+/*
+ * Utility functions for test runners.
+ * (Test runner = class that launch a test)
+ */
+public class RunnerUtil {
+ /**
+ * The Application process must be run concurrently with our tests since
+ * the tests will attach to the Application.
+ * We will run the Application process in a separate thread.
+ *
+ * The Application must be started with flag "-Xshare:off" for the Retransform
+ * test in TestBasics to pass on all platforms.
+ *
+ * The Application will write its pid and shutdownPort in the given outFile.
+ */
+ public static ProcessThread startApplication(String outFile) throws Throwable {
+ String classpath = System.getProperty("test.class.path", ".");
+ String[] args = Utils.addTestJavaOpts(
+ "-Dattach.test=true", "-classpath", classpath, "Application", outFile);
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+ ProcessThread pt = new ProcessThread("runApplication", pb);
+ pt.start();
+ return pt;
+ }
+
+ /**
+ * Will stop the running Application.
+ * First tries to shutdown nicely by connecting to the shut down port.
+ * If that fails, the process will be killed hard with stopProcess().
+ *
+ * If the nice shutdown fails, then an Exception is thrown and the test should fail.
+ *
+ * @param port The shut down port.
+ * @param processThread The process to stop.
+ */
+ public static void stopApplication(int port, ProcessThread processThread) throws Throwable {
+ if (processThread == null) {
+ System.out.println("RunnerUtil.stopApplication ignored since proc is null");
+ return;
+ }
+ try {
+ System.out.println("RunnerUtil.stopApplication waiting to for shutdown");
+ OutputAnalyzer output = ProcessTools.executeTestJvm(
+ "-classpath",
+ System.getProperty("test.class.path", "."),
+ "Shutdown",
+ Integer.toString(port));
+ // Verify that both the Shutdown command and the Application finished ok.
+ output.shouldHaveExitValue(0);
+ processThread.joinAndThrow();
+ processThread.getOutput().shouldHaveExitValue(0);
+ } catch (Throwable t) {
+ System.out.println("RunnerUtil.stopApplication failed. Will kill it hard: " + t);
+ processThread.stopProcess();
+ throw t;
+ }
+ }
+
+ /**
+ * Creates a jar file.
+ * @param args Command to the jar tool.
+ */
+ public static void createJar(String... args) {
+ System.out.println("Running: jar " + Arrays.toString(args));
+ sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jar.run(args)) {
+ throw new RuntimeException("jar failed: args=" + Arrays.toString(args));
+ }
+ }
+
+ /**
+ * Read process info for the running Application.
+ * The Application writes its info to a file with this format:
+ * shutdownPort=42994
+ * pid=19597
+ * done
+ *
+ * The final "done" is used to make sure the complete file has been written
+ * before we try to read it.
+ * This function will wait until the file is available.
+ *
+ * @param filename Path to file to read.
+ * @return The ProcessInfo containing pid and shutdownPort.
+ */
+ public static ProcessInfo readProcessInfo(String filename) throws Throwable {
+ System.out.println("Reading port and pid from file: " + filename);
+ File file = new File(filename);
+ String content = null;
+
+ // Read file or wait for it to be created.
+ while (true) {
+ content = readFile(file);
+ if (content != null && content.indexOf("done") >= 0) {
+ break;
+ }
+ Thread.sleep(100);
+ }
+
+ ProcessInfo info = new ProcessInfo();
+ // search for a line with format: key=nnn
+ Pattern pattern = Pattern.compile("(\\w*)=([0-9]+)\\r?\\n");
+ Matcher matcher = pattern.matcher(content);
+ while (matcher.find()) {
+ String key = matcher.group(1);
+ int value = Integer.parseInt(matcher.group(2));
+ if ("pid".equals(key)) {
+ info.pid = value;
+ } else if ("shutdownPort".equals(key)) {
+ info.shutdownPort = value;
+ }
+ }
+ System.out.println("processInfo.pid:" + info.pid);
+ System.out.println("processInfo.shutdownPort:" + info.shutdownPort);
+ return info;
+ }
+
+ /**
+ * Read the content of a file.
+ * @param file The file to read.
+ * @return The file content or null if file does not exists.
+ */
+ public static String readFile(File file) throws IOException {
+ if (!file.exists()) {
+ return null;
+ }
+ try {
+ byte[] bytes = Files.readAllBytes(file.toPath());
+ String content = new String(bytes);
+ return content;
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ /**
+ * Helper class with info of the running Application.
+ */
+ public static class ProcessInfo {
+ public int pid = -1;
+ public int shutdownPort = -1;
+ }
+
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessThread.java Tue Dec 03 17:06:23 2013 +0100
@@ -37,39 +37,21 @@
/**
* Creates a new {@code ProcessThread} object.
*
- * @param cmd The list of program and its arguments to pass to {@link ProcessBuilder}
+ * @param threadName The name of thread
+ * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
*/
- public ProcessThread(List<String> cmd) {
- super(new ProcessRunnable(cmd));
+ public ProcessThread(String threadName, String... cmd) {
+ super(new ProcessRunnable(new ProcessBuilder(cmd)), threadName);
}
/**
* Creates a new {@code ProcessThread} object.
*
- * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
- */
- public ProcessThread(String... cmd) {
- super(new ProcessRunnable(cmd));
- }
-
- /**
- * Creates a new {@code ProcessThread} object.
- *
- * @param threadName The name of thread
- * @param cmd The list of program and its arguments to pass to {@link ProcessBuilder}
+ * @param threadName The name of thread.
+ * @param pb The ProcessBuilder to execute.
*/
- public ProcessThread(String threadName, List<String> cmd) {
- super(new ProcessRunnable(cmd), threadName);
- }
-
- /**
- * Creates a new {@code ProcessThread} object.
- *
- * @param threadName The name of thread
- * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
- */
- public ProcessThread(String threadName, String... cmd) {
- super(new ProcessRunnable(cmd), threadName);
+ public ProcessThread(String threadName, ProcessBuilder pb) {
+ super(new ProcessRunnable(pb), threadName);
}
/**
@@ -82,6 +64,13 @@
}
/**
+ * @return The process output, or null if the process has not yet completed.
+ */
+ public OutputAnalyzer getOutput() {
+ return ((ProcessRunnable) getRunnable()).getOutput();
+ }
+
+ /**
* {@link Runnable} interface for starting and stopping {@link Process}.
*/
static class ProcessRunnable extends XRun {
@@ -89,26 +78,16 @@
private final ProcessBuilder processBuilder;
private final CountDownLatch latch;
private volatile Process process;
+ private volatile OutputAnalyzer output;
/**
* Creates a new {@code ProcessRunnable} object.
*
- * @param cmd The list of program and its arguments to to pass to {@link ProcessBuilder}
+ * @param pb The {@link ProcessBuilder} to run.
*/
- public ProcessRunnable(List<String> cmd) {
+ public ProcessRunnable(ProcessBuilder pb) {
super();
- this.processBuilder = new ProcessBuilder(cmd);
- this.latch = new CountDownLatch(1);
- }
-
- /**
- * Creates a new {@code ProcessRunnable} object.
- *
- * @param cmd The string array of program and its arguments to to pass to {@link ProcessBuilder}
- */
- public ProcessRunnable(String... cmd) {
- super();
- this.processBuilder = new ProcessBuilder(cmd);
+ this.processBuilder = pb;
this.latch = new CountDownLatch(1);
}
@@ -125,12 +104,16 @@
latch.countDown();
// Will block...
- OutputAnalyzer output = new OutputAnalyzer(this.process);
-
- assertTrue(output.getOutput().isEmpty(), "Should get an empty output, got: "
- + Utils.NEW_LINE + output.getOutput());
- assertNotEquals(output.getExitValue(), 0,
- "Process exited with unexpected exit code");
+ try {
+ output = new OutputAnalyzer(this.process);
+ } catch (Throwable t) {
+ String name = Thread.currentThread().getName();
+ System.out.println(String.format("ProcessThread[%s] failed: %s", name, t.toString()));
+ throw t;
+ } finally {
+ String logMsg = ProcessTools.getProcessLog(processBuilder, output);
+ System.out.println(logMsg);
+ }
}
/**
@@ -142,10 +125,19 @@
// Wait until process is started
latch.await();
if (this.process != null) {
+ System.out.println("ProcessThread.stopProcess() will kill process");
this.process.destroy();
}
}
+ /**
+ * Returns the OutputAnalyzer with stdout/stderr from the process.
+ * @return The process output, or null if process not completed.
+ * @throws InterruptedException
+ */
+ public OutputAnalyzer getOutput() {
+ return output;
+ }
}
}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Tue Dec 03 17:06:23 2013 +0100
@@ -266,4 +266,79 @@
}
}
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvm(String... cmds) throws Throwable {
+ ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds));
+ return executeProcess(pb);
+ }
+
+ /**
+ * Executes a process, waits for it to finish and returns the process output.
+ * @param pb The ProcessBuilder to execute.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable {
+ OutputAnalyzer output = null;
+ try {
+ output = new OutputAnalyzer(pb.start());
+ return output;
+ } catch (Throwable t) {
+ System.out.println("executeProcess() failed: " + t);
+ throw t;
+ } finally {
+ System.out.println(getProcessLog(pb, output));
+ }
+ }
+
+ /**
+ * Executes a process, waits for it to finish and returns the process output.
+ * @param cmds The command line to execute.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeProcess(String... cmds) throws Throwable {
+ return executeProcess(new ProcessBuilder(cmds));
+ }
+
+ /**
+ * Used to log command line, stdout, stderr and exit code from an executed process.
+ * @param pb The executed process.
+ * @param output The output from the process.
+ */
+ public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) {
+ String stderr = output == null ? "null" : output.getStderr();
+ String stdout = output == null ? "null" : output.getStdout();
+ String exitValue = output == null ? "null": Integer.toString(output.getExitValue());
+ StringBuilder logMsg = new StringBuilder();
+ final String nl = System.getProperty("line.separator");
+ logMsg.append("--- ProcessLog ---" + nl);
+ logMsg.append("cmd: " + getCommandLine(pb) + nl);
+ logMsg.append("exitvalue: " + exitValue + nl);
+ logMsg.append("stderr: " + stderr + nl);
+ logMsg.append("stdout: " + stdout + nl);
+ return logMsg.toString();
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ if (pb == null) {
+ return "null";
+ }
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString().trim();
+ }
}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Tue Dec 03 17:06:23 2013 +0100
@@ -33,6 +33,8 @@
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
/**
* Common library for various test helper functions.
@@ -170,4 +172,61 @@
return hostName;
}
+ /**
+ * Uses "jcmd -l" to search for a jvm pid. This function will wait
+ * forever (until jtreg timeout) for the pid to be found.
+ * @param key Regular expression to search for
+ * @return The found pid.
+ */
+ public static int waitForJvmPid(String key) throws Throwable {
+ final long iterationSleepMillis = 250;
+ System.out.println("waitForJvmPid: Waiting for key '" + key + "'");
+ System.out.flush();
+ while (true) {
+ int pid = tryFindJvmPid(key);
+ if (pid >= 0) {
+ return pid;
+ }
+ Thread.sleep(iterationSleepMillis);
+ }
+ }
+
+ /**
+ * Searches for a jvm pid in the output from "jcmd -l".
+ *
+ * Example output from jcmd is:
+ * 12498 sun.tools.jcmd.JCmd -l
+ * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
+ *
+ * @param key A regular expression to search for.
+ * @return The found pid, or -1 if Enot found.
+ * @throws Exception If multiple matching jvms are found.
+ */
+ public static int tryFindJvmPid(String key) throws Throwable {
+ ProcessBuilder pb = null;
+ OutputAnalyzer output = null;
+ try {
+ JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd");
+ jcmdLauncher.addToolArg("-l");
+ output = ProcessTools.executeProcess(jcmdLauncher.getCommand());
+ output.shouldHaveExitValue(0);
+
+ // Search for a line starting with numbers (pid), follwed by the key.
+ Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n");
+ Matcher matcher = pattern.matcher(output.getStdout());
+
+ int pid = -1;
+ if (matcher.find()) {
+ pid = Integer.parseInt(matcher.group(1));
+ System.out.println("findJvmPid.pid: " + pid);
+ if (matcher.find()) {
+ throw new Exception("Found multiple JVM pids for key: " + key);
+ }
+ }
+ return pid;
+ } catch (Throwable t) {
+ System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t));
+ throw t;
+ }
+ }
}
--- a/jdk/test/sun/tools/jstatd/JstatdTest.java Tue Dec 03 23:09:17 2013 -0800
+++ b/jdk/test/sun/tools/jstatd/JstatdTest.java Tue Dec 03 17:06:23 2013 +0100
@@ -353,6 +353,14 @@
} finally {
cleanUpThread(jstatdThread);
}
+
+ // Verify output from jstatd
+ OutputAnalyzer output = jstatdThread.getOutput();
+ assertTrue(output.getOutput().isEmpty(),
+ "jstatd should get an empty output, got: "
+ + Utils.NEW_LINE + output.getOutput());
+ assertNotEquals(output.getExitValue(), 0,
+ "jstatd process exited with unexpected exit code");
}
}