diff --git a/test/ProblemList.txt b/test/ProblemList.txt index 47c05aaf7d87d748400f80a0500df8f83cc04123..cd0b1fdc3446ad8688f7e65f63636b9f04e823d9 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -182,9 +182,6 @@ com/sun/net/httpserver/bugs/6725892/Test.java generic-all # Filed 7036666 com/sun/net/httpserver/Test9a.java generic-all -# 7079145 java/net/ipv6tests/UdpTest.java hang at IPv6 only data exchange -java/net/ipv6tests/UdpTest.java linux-all - # 7102670 java/net/InetAddress/CheckJNI.java linux-all diff --git a/test/TEST.groups b/test/TEST.groups index c680117cc93280c079a6af567fae82c7a47e2545..77fae723f98dccc1a0b5f7b06eaf74c716b5e03c 100644 --- a/test/TEST.groups +++ b/test/TEST.groups @@ -325,7 +325,8 @@ needs_jdk = \ jdk/lambda/separate/Compiler.java \ sun/management/jdp/JdpTest.sh \ sun/management/jmxremote/bootstrap/JvmstatCountersTest.java \ - sun/management/jmxremote/bootstrap/LocalManagementTest.sh \ + sun/management/jmxremote/bootstrap/LocalManagementTest.java \ + sun/management/jmxremote/bootstrap/CustomLauncherTest.java \ sun/misc/JarIndex/metaInfFilenames/Basic.java \ sun/misc/JarIndex/JarIndexMergeForClassLoaderTest.java \ sun/reflect/CallerSensitive/CallerSensitiveFinder.java \ diff --git a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java index 16783aebc06e2858ddb7553c4a0339d02055a9d7..29b4e38b1f6ff40921ca640ef428af62cc8e9600 100644 --- a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java +++ b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -25,24 +25,127 @@ package jdk.testlibrary; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.PrintWriter; 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 java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Predicate; import sun.management.VMManagement; public final class ProcessTools { + private static final class LineForwarder extends StreamPumper.LinePump { + private final PrintStream ps; + private final String prefix; + LineForwarder(String prefix, PrintStream os) { + this.ps = os; + this.prefix = prefix; + } + @Override + protected void processLine(String line) { + ps.println("[" + prefix + "] " + line); + } + } private ProcessTools() { } + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + * @param name The process name + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder) + throws IOException { + Process p = null; + try { + p = startProcess(name, processBuilder, null, -1, TimeUnit.NANOSECONDS); + } catch (InterruptedException | TimeoutException e) { + // can't ever happen + } + return p; + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT + *

+ * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + Process p = processBuilder.start(); + StreamPumper stdout = new StreamPumper(p.getInputStream()); + StreamPumper stderr = new StreamPumper(p.getErrorStream()); + + stdout.addPump(new LineForwarder(name, System.out)); + stderr.addPump(new LineForwarder(name, System.err)); + final Phaser phs = new Phaser(1); + if (linePredicate != null) { + stdout.addPump(new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + if (linePredicate.test(line)) { + if (phs.getRegisteredParties() > 0) { + phs.arriveAndDeregister(); + } + } + } + }); + } + Future stdoutTask = stdout.process(); + Future stderrTask = stderr.process(); + + try { + if (timeout > -1) { + phs.awaitAdvanceInterruptibly(0, timeout, unit); + } + } catch (TimeoutException | InterruptedException e) { + stdoutTask.cancel(true); + stderrTask.cancel(true); + throw e; + } + + return p; + } + /** * Pumps stdout and stderr from running the process into a String. * - * @param processHandler + * @param processBuilder * ProcessHandler to run. * @return Output from process. * @throws IOException @@ -69,22 +172,19 @@ public final class ProcessTools { 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(); + Future outTask = outPumper.process(); + Future errTask = errPumper.process(); try { process.waitFor(); - outPumperThread.join(); - errPumperThread.join(); + outTask.get(); + errTask.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return null; + } catch (ExecutionException e) { + throw new IOException(e); } return new OutputBuffer(stdoutBuffer.toString(), diff --git a/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java b/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java index 60adca4e3dae485ef15b0cb496cb1adfd4b17473..224dcb2824720de6d9596f620d80f1115b3574a5 100644 --- a/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java +++ b/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java @@ -23,16 +23,65 @@ package jdk.testlibrary; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.InputStream; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicBoolean; public final class StreamPumper implements Runnable { private static final int BUF_SIZE = 256; - private final OutputStream out; + /** + * Pump will be called by the StreamPumper to process the incoming data + */ + abstract public static class Pump { + abstract void register(StreamPumper d); + } + + /** + * OutputStream -> Pump adapter + */ + final public static class StreamPump extends Pump { + private final OutputStream out; + public StreamPump(OutputStream out) { + this.out = out; + } + + @Override + void register(StreamPumper sp) { + sp.addOutputStream(out); + } + } + + /** + * Used to process the incoming data line-by-line + */ + abstract public static class LinePump extends Pump { + @Override + final void register(StreamPumper sp) { + sp.addLineProcessor(this); + } + + abstract protected void processLine(String line); + } + private final InputStream in; + private final Set outStreams = new HashSet<>(); + private final Set linePumps = new HashSet<>(); + + private final AtomicBoolean processing = new AtomicBoolean(false); + private final FutureTask processingTask = new FutureTask(this, null); + + public StreamPumper(InputStream in) { + this.in = in; + } /** * Create a StreamPumper that reads from in and writes to out. @@ -43,8 +92,8 @@ public final class StreamPumper implements Runnable { * The stream to write to. */ public StreamPumper(InputStream in, OutputStream out) { - this.in = in; - this.out = out; + this(in); + this.addOutputStream(out); } /** @@ -54,25 +103,97 @@ public final class StreamPumper implements Runnable { */ @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); + try (BufferedInputStream is = new BufferedInputStream(in)) { + ByteArrayOutputStream lineBos = new ByteArrayOutputStream(); + byte[] buf = new byte[BUF_SIZE]; + int len = 0; + int linelen = 0; + + while ((len = is.read(buf)) > 0 && !Thread.interrupted()) { + for(OutputStream out : outStreams) { + out.write(buf, 0, len); + } + if (!linePumps.isEmpty()) { + int i = 0; + int lastcrlf = -1; + while (i < len) { + if (buf[i] == '\n' || buf[i] == '\r') { + int bufLinelen = i - lastcrlf - 1; + if (bufLinelen > 0) { + lineBos.write(buf, lastcrlf + 1, bufLinelen); + } + linelen += bufLinelen; + + if (linelen > 0) { + lineBos.flush(); + final String line = lineBos.toString(); + linePumps.stream().forEach((lp) -> { + lp.processLine(line); + }); + lineBos.reset(); + linelen = 0; + } + lastcrlf = i; + } + + i++; + } + if (lastcrlf == -1) { + lineBos.write(buf, 0, len); + linelen += len; + } else if (lastcrlf < len - 1) { + lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1); + linelen += len - lastcrlf - 1; + } + } } + } catch (IOException e) { - // Just abort if something like this happens. e.printStackTrace(); } finally { + for(OutputStream out : outStreams) { + try { + out.flush(); + } catch (IOException e) {} + } try { - localOut.flush(); in.close(); - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException e) {} + } + } + + final void addOutputStream(OutputStream out) { + outStreams.add(out); + } + + final void addLineProcessor(LinePump lp) { + linePumps.add(lp); + } + + final public StreamPumper addPump(Pump ... pump) { + if (processing.get()) { + throw new IllegalStateException("Can not modify pumper while " + + "processing is in progress"); + } + for(Pump p : pump) { + p.register(this); } + return this; + } + + final public Future process() { + if (!processing.compareAndSet(false, true)) { + throw new IllegalStateException("Can not re-run the processing"); + } + Thread t = new Thread(new Runnable() { + @Override + public void run() { + processingTask.run(); + } + }); + t.setDaemon(true); + t.start(); + + return processingTask; } } diff --git a/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java b/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2f77cce56308b53dc6c3c03f5c8591d6eaa9684d --- /dev/null +++ b/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java @@ -0,0 +1,221 @@ +/* + * 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.File; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import jdk.testlibrary.JdkFinder; +import jdk.testlibrary.ProcessTools; + +/** + * @test + * @bug 6434402 8004926 + * @library ../../../../lib/testlibrary + * @build TestManager TestApplication CustomLauncherTest + * @run main CustomLauncherTest + * @author Jaroslav Bachorik + */ +public class CustomLauncherTest { + private static final String TEST_CLASSES = System.getProperty("test.classes"); + private static final String TEST_JDK = System.getProperty("test.jdk"); + + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String OSNAME = System.getProperty("os.name"); + private static final String ARCH; + private static final String LIBARCH; + + static { + // magic with os.arch + String osarch = System.getProperty("os.arch"); + switch (osarch) { + case "i386": + case "i486": + case "i586": + case "i686": + case "i786": + case "i886": + case "i986": { + ARCH = "i586"; + break; + } + case "x86_64": + case "amd64": { + ARCH = "amd64"; + break; + } + default: { + ARCH = osarch; + } + } + LIBARCH = ARCH.equals("i586") ? "i386" : ARCH; + } + + public static void main(String[] args) throws Exception { + if (TEST_CLASSES == null || TEST_CLASSES.isEmpty()) { + System.out.println("Test is designed to be run from jtreg only"); + return; + } + + String PLATFORM = ""; + switch (OSNAME.toLowerCase()) { + case "linux": { + PLATFORM = "linux"; + break; + } + case "sunos": { + PLATFORM = "solaris"; + break; + } + default: { + System.out.println("Test not designed to run on this operating " + + "system (" + OSNAME + "), skipping..."); + return; + } + } + + String LAUNCHER = TEST_SRC + File.separator + PLATFORM + "-" + ARCH + + File.separator + "launcher"; + + final FileSystem FS = FileSystems.getDefault(); + final boolean hasLauncher = Files.isExecutable(FS.getPath(LAUNCHER)); + if (!hasLauncher) { + System.out.println("Launcher [" + LAUNCHER + "] does not exist. Skipping the test."); + return; + } + + Path libjvmPath = findLibjvm(FS); + if (libjvmPath == null) { + throw new Error("Unable to locate 'libjvm.so' in " + TEST_JDK); + } + + Process serverPrc = null, clientPrc = null; + + try { + System.out.println("Starting custom launcher:"); + System.out.println("========================="); + System.out.println(" launcher : " + LAUNCHER); + System.out.println(" libjvm : " + libjvmPath.toString()); + System.out.println(" classpath : " + TEST_CLASSES); + ProcessBuilder server = new ProcessBuilder(LAUNCHER, libjvmPath.toString(), TEST_CLASSES, "TestApplication"); + + final AtomicReference port = new AtomicReference<>(); + final AtomicReference pid = new AtomicReference<>(); + + serverPrc = ProcessTools.startProcess( + "Launcher", + server, + (String line) -> { + if (line.startsWith("port:")) { + port.set(line.split("\\:")[1]); + } else if (line.startsWith("pid:")) { + pid.set(line.split("\\:")[1]); + } else if (line.startsWith("waiting")) { + return true; + } + return false; + }, + 5, + TimeUnit.SECONDS + ); + + System.out.println("Attaching test manager:"); + System.out.println("========================="); + System.out.println(" PID : " + pid.get()); + System.out.println(" shutdown port : " + port.get()); + + ProcessBuilder client = ProcessTools.createJavaProcessBuilder( + "-cp", + TEST_CLASSES + + File.pathSeparator + + TEST_JDK + + File.separator + + "lib" + + File.separator + + "tools.jar", + "TestManager", + pid.get(), + port.get(), + "true" + ); + + clientPrc = ProcessTools.startProcess( + "TestManager", + client, + (String line) -> line.startsWith("Starting TestManager for PID"), + 10, + TimeUnit.SECONDS + ); + + int clientExitCode = clientPrc.waitFor(); + int serverExitCode = serverPrc.waitFor(); + + if (clientExitCode != 0 || serverExitCode != 0) { + throw new Error("Test failed"); + } + } finally { + if (clientPrc != null) { + clientPrc.destroy(); + clientPrc.waitFor(); + } + if (serverPrc != null) { + serverPrc.destroy(); + serverPrc.waitFor(); + } + } + } + + private static Path findLibjvm(FileSystem FS) { + Path libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "jre", "lib", LIBARCH)); + if (libjvmPath == null) { + libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "lib", LIBARCH)); + } + return libjvmPath; + } + + private static Path findLibjvm(Path libPath) { + // ARCH/libjvm.so -> ARCH/server/libjvm.so -> ARCH/client/libjvm.so + Path libjvmPath = libPath.resolve("libjvm.so"); + if (isFileOk(libjvmPath)) { + return libjvmPath; + } + libjvmPath = libPath.resolve("server/libjvm.so"); + if (isFileOk(libjvmPath)) { + return libjvmPath; + } + libjvmPath = libPath.resolve("client/libjvm.so"); + if (isFileOk(libPath)) { + return libjvmPath; + } + + return null; + } + + private static boolean isFileOk(Path path) { + return Files.isRegularFile(path) && Files.isReadable(path); + } +} diff --git a/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh b/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh deleted file mode 100644 index 8622fba94a0fa17f26a2db9124689c0eac684642..0000000000000000000000000000000000000000 --- a/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 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. -# - - -# @test -# @bug 6434402 -# @summary Start an application using a custom launcher and check that -# a management tool can connect. -# -# @build TestManager TestApplication -# @run shell CustomLauncherTest.sh - -# -# Check we are run from jtreg -# -if [ -z "${TESTCLASSES}" ]; then - echo "Test is designed to be run from jtreg only" - exit 0 -fi - -# -# For now this test passes silently on Windows - this means the test only -# has to locate libjvm.so. Also $! is not reliable on some releases of MKS. -#{ -OS=`uname -s` -if [ "$OS" != "Linux" -a "$OS" != "SunOS" ]; then - echo "Test not designed to run on this operating system, skipping..." - exit 0 -fi - -# -# Locate the custom launcher for this platform -# -PLATFORM=unknown -ARCH=unknown -if [ "$OS" = "SunOS" ]; then - PLATFORM=solaris - case "`uname -p`" in - i[3-9]86) - ARCH=i586 - ;; - sparc) - ARCH=sparc - ;; - esac -else - PLATFORM=linux - case "`uname -m`" in - i[3-6]86) - ARCH=i586 - ;; - x86_64) - ARCH=amd64 - ;; - esac -fi - - -# -# On x86 the native libraries are in lib/i386 for -# compatability reasons -# -if [ "$ARCH" = "i586" ]; then - LIBARCH="i386" -else - LIBARCH=$ARCH -fi - - -# -# Check that a custom launcher exists for this platform -# -LAUNCHER="${TESTSRC}/${PLATFORM}-${ARCH}/launcher" -if [ ! -x "${LAUNCHER}" ]; then - echo "${LAUNCHER} not found" - exit 0 -fi - -# -# Locate the libjvm.so library -# -JVMLIB="${TESTJAVA}/jre/lib/${LIBARCH}/client/libjvm.so" -if [ ! -f "${JVMLIB}" ]; then - JVMLIB="${TESTJAVA}/jre/lib/${LIBARCH}/server/libjvm.so" - if [ ! -f "${JVMLIB}" ]; then - JVMLIB="${TESTJAVA}/lib/${LIBARCH}/client/libjvm.so" - if [ ! -f "${JVMLIB}" ]; then - JVMLIB="${TESTJAVA}/lib/${LIBARCH}/serevr/libjvm.so" - if [ ! -f "${JVMLIB}" ]; then - echo "Unable to locate libjvm.so in ${TESTJAVA}" - exit 1 - fi - fi - fi -fi - -# -# Start the VM -# -outputfile=${TESTCLASSES}/Test.out -rm -f ${outputfile} - -echo '' -echo "Starting custom launcher..." -echo " launcher: ${LAUNCHER}" -echo " libjvm: ${JVMLIB}" -echo "classpath: ${TESTCLASSES}" - - -${LAUNCHER} ${JVMLIB} ${TESTCLASSES} TestApplication > ${outputfile} & -pid=$! - -# Wait for managed VM to startup (although this looks like a potentially -# infinate loop, the framework will eventually kill it) -echo "Waiting for TestAppication to test..." -attempts=0 -while true; do - sleep 1 - port=`tail -1 ${outputfile}` - 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 - -# Start the manager - this should connect to VM -${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \ - TestManager $pid $port true -if [ $? != 0 ]; then - echo "Test failed" - exit 1 -fi -exit 0 diff --git a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9d7a518ce1cf4b70104a674f3fc00f8aa5ae7cfe --- /dev/null +++ b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java @@ -0,0 +1,237 @@ +/* + * 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.File; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @test + * @library ../../../../lib/testlibrary + * @bug 5016507 6173612 6319776 6342019 6484550 8004926 + * @summary Start a managed VM and test that a management tool can connect + * without connection or username/password details. + * TestManager will attempt a connection to the address obtained from + * both agent properties and jvmstat buffer. + * @build TestManager TestApplication + * @run main/timeout=300 LocalManagementTest + */ + +import jdk.testlibrary.ProcessTools; + +public class LocalManagementTest { + private static final String TEST_CLASSES = System.getProperty("test.classes"); + private static final String TEST_JDK = System.getProperty("test.jdk"); + + public static void main(String[] args) throws Exception { + int failures = 0; + for(Method m : LocalManagementTest.class.getDeclaredMethods()) { + if (Modifier.isStatic(m.getModifiers()) && + m.getName().startsWith("test")) { + m.setAccessible(true); + try { + System.out.println(m.getName()); + System.out.println("=========="); + Boolean rslt = (Boolean)m.invoke(null); + if (!rslt) { + System.err.println(m.getName() + " failed"); + failures++; + } + } catch (Exception e) { + e.printStackTrace(); + failures++; + } + } + } + if (failures > 0) { + throw new Error("Test failed"); + } + } + + private static boolean test1() throws Exception { + return doTest("-Dcom.sun.management.jmxremote"); + } + + private static boolean test2() throws Exception { + Path agentPath = findAgent(); + if (agentPath != null) { + String agent = agentPath.toString(); + return doTest("-javaagent:" + agent); + } else { + return false; + } + } + + /** + * no args (blank) - manager should attach and start agent + */ + private static boolean test3() throws Exception { + return doTest(null); + } + + /** + * sanity check arguments to management-agent.jar + */ + private static boolean test4() throws Exception { + Path agentPath = findAgent(); + if (agentPath != null) { + ProcessBuilder builder = ProcessTools.createJavaProcessBuilder( + "-javaagent:" + agentPath.toString() + + "=com.sun.management.jmxremote.port=7775," + + "com.sun.management.jmxremote.authenticate=false," + + "com.sun.management.jmxremote.ssl=false", + "TestApplication", + "-exit" + ); + + Process prc = null; + try { + prc = ProcessTools.startProcess( + "TestApplication", + builder + ); + int exitCode = prc.waitFor(); + return exitCode == 0; + } finally { + if (prc != null) { + prc.destroy(); + prc.waitFor(); + } + } + } + return false; + } + + /** + * use DNS-only name service + */ + private static boolean test5() throws Exception { + return doTest("-Dsun.net.spi.namservice.provider.1=\"dns,sun\""); + } + + private static Path findAgent() { + FileSystem FS = FileSystems.getDefault(); + Path agentPath = FS.getPath( + TEST_JDK, "jre", "lib", "management-agent.jar" + ); + if (!isFileOk(agentPath)) { + agentPath = FS.getPath( + TEST_JDK, "lib", "management-agent.jar" + ); + } + if (!isFileOk(agentPath)) { + System.err.println("Can not locate management-agent.jar"); + return null; + } + return agentPath; + } + + private static boolean isFileOk(Path path) { + return Files.isRegularFile(path) && Files.isReadable(path); + } + + private static boolean doTest(String arg) throws Exception { + List args = new ArrayList<>(); + if (arg != null) { + args.add(arg); + } + args.add("TestApplication"); + ProcessBuilder server = ProcessTools.createJavaProcessBuilder( + args.toArray(new String[args.size()]) + ); + + Process serverPrc = null, clientPrc = null; + try { + final AtomicReference port = new AtomicReference<>(); + final AtomicReference pid = new AtomicReference<>(); + + serverPrc = ProcessTools.startProcess( + "TestApplication", + server, + (String line) -> { + if (line.startsWith("port:")) { + port.set(line.split("\\:")[1]); + } else if (line.startsWith("pid:")) { + pid.set(line.split("\\:")[1]); + } else if (line.startsWith("waiting")) { + return true; + } + return false; + }, + 5, + TimeUnit.SECONDS + ); + + System.out.println("Attaching test manager:"); + System.out.println("========================="); + System.out.println(" PID : " + pid.get()); + System.out.println(" shutdown port : " + port.get()); + + ProcessBuilder client = ProcessTools.createJavaProcessBuilder( + "-cp", + TEST_CLASSES + + File.pathSeparator + + TEST_JDK + + File.separator + + "lib" + + File.separator + + "tools.jar", + "TestManager", + pid.get(), + port.get(), + "true" + ); + + clientPrc = ProcessTools.startProcess( + "TestManager", + client, + (String line) -> line.startsWith("Starting TestManager for PID"), + 10, + TimeUnit.SECONDS + ); + + int clientExitCode = clientPrc.waitFor(); + int serverExitCode = serverPrc.waitFor(); + return clientExitCode == 0 && serverExitCode == 0; + } finally { + if (clientPrc != null) { + System.out.println("Stopping process " + clientPrc); + clientPrc.destroy(); + clientPrc.waitFor(); + } + if (serverPrc != null) { + System.out.println("Stopping process " + serverPrc); + serverPrc.destroy(); + serverPrc.waitFor(); + } + } + } +} \ No newline at end of file diff --git a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh b/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh deleted file mode 100644 index 7338cbe8600fb9326bb9177ff84e6b66f99b7c0b..0000000000000000000000000000000000000000 --- a/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2004, 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. -# - - -# @test -# @bug 5016507 6173612 6319776 6342019 6484550 -# @summary Start a managed VM and test that a management tool can connect -# without connection or username/password details. -# TestManager will attempt a connection to the address obtained from -# both agent properties and jvmstat buffer. -# -# @build TestManager TestApplication -# @run shell/timeout=300 LocalManagementTest.sh - - -doTest() -{ - echo '' - - outputfile=${TESTCLASSES}/Test.out - rm -f ${outputfile} - - # Start VM with given options - echo "+ $JAVA ${TESTVMOPTS} $1 Test" - $JAVA ${TESTVMOPTS} $1 TestApplication > ${outputfile}& - pid=$! - - # Wait for managed VM to startup - echo "Waiting for VM to startup..." - attempts=0 - while true; do - sleep 1 - port=`tail -1 ${outputfile}` - 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 - - # Start the manager - this should connect to VM - sh -xc "$JAVA ${TESTVMOPTS} -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \ - TestManager $pid $port" 2>&1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - - -# Check we are run from jtreg -if [ -z "${TESTCLASSES}" ]; then - echo "Test is designed to be run from jtreg only" - exit 0 -fi - -# For now this test passes silently on Windows - there are 2 reasons -# to skip it :- -# -# 1. No jstat instrumentation buffers if FAT32 so need -# -XX:+PerfBypassFileSystemCheck -# 2. $! is used to get the pid of the created process but it's not -# reliable on older versions of MKS. Also negative pids are returned -# on Windows 98. - -os=`uname -s` -if [ "$os" != "Linux" -a "$os" != "SunOS" ]; then - echo "Test not designed to run on this operating system, skipping..." - exit 0 -fi - -JAVA=${TESTJAVA}/bin/java -CLASSPATH=${TESTCLASSES} -export CLASSPATH - -failures=0 - -# Test 1 -doTest "-Dcom.sun.management.jmxremote" - -# Test 2 -AGENT="${TESTJAVA}/jre/lib/management-agent.jar" -if [ ! -f ${AGENT} ]; then - AGENT="${TESTJAVA}/lib/management-agent.jar" -fi -doTest "-javaagent:${AGENT}" - -# Test 3 - no args (blank) - manager should attach and start agent -doTest " " - -# Test 4 - sanity check arguments to management-agent.jar -echo ' ' -sh -xc "${JAVA} ${TESTVMOPTS} -javaagent:${AGENT}=com.sun.management.jmxremote.port=7775,\ -com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false \ - TestApplication -exit" 2>&1 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi - -# Test 5 - use DNS-only name service -doTest "-Dsun.net.spi.namservice.provider.1=\"dns,sun\"" - -# -# Results -# -echo '' -if [ $failures -gt 0 ]; - then echo "$failures test(s) failed"; - else echo "All test(s) passed"; fi -exit $failures - diff --git a/test/sun/management/jmxremote/bootstrap/TestApplication.java b/test/sun/management/jmxremote/bootstrap/TestApplication.java index 17816b9db1863d66d72b0f140efac133496b3263..5d6ca2b6a271dfe2881837ac199312bb377277c0 100644 --- a/test/sun/management/jmxremote/bootstrap/TestApplication.java +++ b/test/sun/management/jmxremote/bootstrap/TestApplication.java @@ -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 @@ -24,14 +24,18 @@ /* * * - * A test "application" used by unit test LocalManagementTest.sh. This - * application binds to some random port, prints the port number to - * standard output, waits for somebody to connect, and then shuts down. + * A test "application" used by unit tests - + * LocalManagementTest.java, CustomLauncherTest.java. + * This application binds to some random port, prints its pid and + * the port number to standard output, waits for somebody to connect, + * and then shuts down. */ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; +import jdk.testlibrary.ProcessTools; + public class TestApplication { public static void main(String[] args) throws IOException { // Some tests require the application to exit immediately @@ -43,8 +47,17 @@ public class TestApplication { ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort(); - // signal test that we are started - do not remove this line!! - System.out.println(port); + int pid = -1; + try { + pid = ProcessTools.getProcessId(); + } catch (Exception e) { + e.printStackTrace(); + } + + // signal test that we are started - do not remove these lines!! + System.out.println("port:" + port); + System.out.println("pid:" + pid); + System.out.println("waiting for the manager ..."); System.out.flush(); // wait for manager to connect diff --git a/test/sun/management/jmxremote/bootstrap/TestManager.java b/test/sun/management/jmxremote/bootstrap/TestManager.java index 379739adf29b2be5ee1601ee87a9a3fc604e15d9..4495c2d07fe60e9b567dd1677b0650568171dfb5 100644 --- a/test/sun/management/jmxremote/bootstrap/TestManager.java +++ b/test/sun/management/jmxremote/bootstrap/TestManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 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 @@ -24,7 +24,8 @@ /* * * - * A test "management tool" used by unit test LocalManagementTest.sh. + * A test "management tool" used by unit tests - + * LocalManagementTest.java, CustomLauncherTest.java * * Usage: java TestManager * @@ -32,8 +33,6 @@ * TCP port is used to shutdown the application. */ import javax.management.MBeanServerConnection; -import javax.management.MBeanServerInvocationHandler; -import javax.management.ObjectName; import javax.management.remote.JMXServiceURL; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnector; @@ -43,7 +42,6 @@ import java.net.Socket; import java.net.InetSocketAddress; import java.io.File; import java.io.IOException; -import java.util.Properties; // Sun specific import com.sun.tools.attach.VirtualMachine; @@ -111,6 +109,8 @@ public class TestManager { "com.sun.management.jmxremote.localConnectorAddress"; public static void main(String[] args) throws Exception { String pid = args[0]; // pid as a string + System.out.println("Starting TestManager for PID = " + pid); + System.out.flush(); VirtualMachine vm = VirtualMachine.attach(pid); String agentPropLocalConnectorAddress = (String) @@ -140,7 +140,6 @@ public class TestManager { System.out.println("Testing the connector address from jvmstat buffer"); connect(pid, jvmstatLocalConnectorAddress); - // Shutdown application int port = Integer.parseInt(args[1]); System.out.println("Shutdown process via TCP port: " + port); diff --git a/test/sun/management/jmxremote/bootstrap/linux-amd64/launcher b/test/sun/management/jmxremote/bootstrap/linux-amd64/launcher new file mode 100644 index 0000000000000000000000000000000000000000..6df223c91c716644ceeed126c2971c48969fa295 Binary files /dev/null and b/test/sun/management/jmxremote/bootstrap/linux-amd64/launcher differ