diff --git a/test/ProblemList.txt b/test/ProblemList.txt index 25ada7c21ca6d8f5cdc3f6cdee4f42a57e7ae181..bd0ee6e08c7827876a5ef88e247c0a7651a44143 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -273,3 +273,10 @@ tools/launcher/FXLauncherTest.java linux-all java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all ############################################################################ + +# svc_tools + +# 8031482 +sun/tools/jcmd/TestJcmdSanity.java windows-all + +############################################################################ \ No newline at end of file diff --git a/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java b/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java index 14599c998bd51e46f35168772e93bbd7e69fe297..1837ceae1738b94354d5439df50f2fc5f41959ae 100644 --- a/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java +++ b/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java @@ -26,34 +26,91 @@ package jdk.testlibrary; import java.util.Arrays; /** - * Super class for tests which need to attach jcmd to the current process. + * Helper class for starting jcmd process. + *
+ * - jcmd will send diagnostic requests to the current java process:
+ *      jcmd pid_to_current_process PerfCounter.print
+ * - jcmd will be run without sending request to any JVM
+ *      jcmd -h
+ * 
*/ -public class JcmdBase { +public final class JcmdBase { private static ProcessBuilder processBuilder = new ProcessBuilder(); + private JcmdBase() { + // Private constructor to prevent class instantiation + } + /** - * Attach jcmd to the current process + * Sends the diagnostic command request to the current process * - * @param toolArgs - * jcmd command line parameters, e.g. VM.flags - * @return jcmd output - * @throws Exception + * @see #jcmd(boolean, String[], String[]) */ - public final static OutputAnalyzer jcmd(String... toolArgs) + public final static OutputAnalyzer jcmd(String... jcmdArgs) throws Exception { + return jcmd(true, null, jcmdArgs); + } + + /** + * Sends the diagnostic command request to the current process. + * jcmd will be run with specified {@code vmArgs}. + * + * @see #jcmd(boolean, String[], String[]) + */ + public final static OutputAnalyzer jcmd(String[] vmArgs, + String[] jcmdArgs) throws Exception { + return jcmd(true, vmArgs, jcmdArgs); + } + + /** + * Runs jcmd without sending request to any JVM + * + * @see #jcmd(boolean, String[], String[]) + */ + public final static OutputAnalyzer jcmdNoPid(String[] vmArgs, + String[] jcmdArgs) throws Exception { + return jcmd(false, vmArgs, jcmdArgs); + } + + /** + * If {@code requestToCurrentProcess} is {@code true} + * sends a diagnostic command request to the current process. + * If {@code requestToCurrentProcess} is {@code false} + * runs jcmd without sending request to any JVM. + * + * @param requestToCurrentProcess + * Defines if jcmd will send request to the current process + * @param vmArgs + * jcmd will be run with VM arguments specified, + * e.g. -XX:+UsePerfData + * @param jcmdArgs + * jcmd will be run with option or command and its arguments + * specified, e.g. VM.flags + * @return The output from {@link OutputAnalyzer} object + * @throws Exception + */ + private static final OutputAnalyzer jcmd(boolean requestToCurrentProcess, + String[] vmArgs, String[] jcmdArgs) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jcmd"); - launcher.addToolArg(Integer.toString(ProcessTools.getProcessId())); - for (String toolArg : toolArgs) { - launcher.addToolArg(toolArg); + if (vmArgs != null) { + for (String vmArg : vmArgs) { + launcher.addVMArg(vmArg); + } + } + if (requestToCurrentProcess) { + launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); + } + if (jcmdArgs != null) { + for (String toolArg : jcmdArgs) { + launcher.addToolArg(toolArg); + } } processBuilder.command(launcher.getCommand()); System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); OutputAnalyzer output = new OutputAnalyzer(processBuilder.start()); System.out.println(output.getOutput()); - output.shouldHaveExitValue(0); - return output; } diff --git a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java index d39c0ab2ce2102a64e6cf35a935ba7aea00b5862..7c0d36400ba2b13d6e0fb74c3403a4b4c8a57923 100644 --- a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java +++ b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java @@ -23,11 +23,14 @@ package jdk.testlibrary; +import static jdk.testlibrary.Asserts.*; + import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.Scanner; /** * Utility class for verifying output and exit value from a {@code Process}. @@ -397,22 +400,105 @@ public final class OutputAnalyzer { return exitValue; } + /** * Get the contents of the output buffer (stdout and stderr) as list of strings. * Output will be split by system property 'line.separator'. * * @return Contents of the output buffer as list of strings */ - public List asLines() { - return asLines(getOutput()); - } + public List asLines() { + return asLines(getOutput()); + } - private List asLines(String buffer) { + public List asLines(String buffer) { List l = new ArrayList<>(); + String[] a = buffer.split(Utils.NEW_LINE); + for (String string : a) { l.add(string); } return l; } + + /** + * Check if there is a line matching {@code pattern} and return its index + * + * @param pattern Matching pattern + * @return Index of first matching line + */ + private int indexOf(List lines, String pattern) { + for (int i = 0; i < lines.size(); i++) { + if (lines.get(i).matches (pattern)) { + return i; + } + } + return -1; + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLine(String pattern) { + return shouldMatchByLine(null, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineFrom(String from, String pattern) { + return shouldMatchByLine(from, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineTo(String to, String pattern) { + return shouldMatchByLine(null, to, pattern); + } + + /** + * Verify that the stdout and stderr contents of output buffer match the + * {@code pattern} line by line. The whole output could be matched or + * just a subset of it. + * + * @param from + * The line from where output will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where output will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int shouldMatchByLine(String from, String to, String pattern) { + List lines = asLines(); + + int fromIndex = 0; + if (from != null) { + fromIndex = indexOf(lines, from); + assertGreaterThan(fromIndex, -1, + "The line/pattern '" + from + "' from where the output should match can not be found"); + } + + int toIndex = lines.size(); + if (to != null) { + toIndex = indexOf(lines, to); + assertGreaterThan(toIndex, -1, + "The line/pattern '" + to + "' until where the output should match can not be found"); + } + + List subList = lines.subList(fromIndex, toIndex); + int matchedCount = 0; + for (String line : subList) { + assertTrue(line.matches(pattern), + "The line '" + line + "' does not match pattern '" + pattern + "'"); + matchedCount++; + } + + return matchedCount; + } + } diff --git a/test/lib/testlibrary/jdk/testlibrary/Utils.java b/test/lib/testlibrary/jdk/testlibrary/Utils.java index 67af0cddc9a7e21cc3fbd20624d5471fdb0610f4..c21923460b614577009990b3722a49e00ddfffbc 100644 --- a/test/lib/testlibrary/jdk/testlibrary/Utils.java +++ b/test/lib/testlibrary/jdk/testlibrary/Utils.java @@ -25,6 +25,9 @@ package jdk.testlibrary; import static jdk.testlibrary.Asserts.assertTrue; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; @@ -241,7 +244,6 @@ public final class Utils { * @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"); @@ -268,6 +270,25 @@ public final class Utils { } } + /** + * Returns file content as a list of strings + * + * @param file File to operate on + * @return List of strings + * @throws IOException + */ + public static List fileAsList(File file) throws IOException { + assertTrue(file.exists() && file.isFile(), + file.getAbsolutePath() + " does not exist or not a file"); + List output = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) { + while (reader.ready()) { + output.add(reader.readLine().replace(NEW_LINE, "")); + } + } + return output; + } + /** * Adjusts the provided timeout value for the TIMEOUT_FACTOR * @param tOut the timeout value to be adjusted diff --git a/test/sun/tools/jcmd/TestJcmdDefaults.java b/test/sun/tools/jcmd/TestJcmdDefaults.java new file mode 100644 index 0000000000000000000000000000000000000000..a5310862859fc14cbe853d2d9e69a4f5b19d1c6a --- /dev/null +++ b/test/sun/tools/jcmd/TestJcmdDefaults.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.testlibrary.Asserts.*; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import jdk.testlibrary.JcmdBase; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.Utils; + +/** + * Unit test for jcmd utility. Tests jcmd options which do not send + * requests to a specific JVM process. + */ +/* + * @test + * @bug 7104647 + * @library /lib/testlibrary + * @run main TestJcmdDefaults + */ +public class TestJcmdDefaults { + + private static final String TEST_SRC = System.getProperty("test.src").trim(); + private static final String[] VM_ARGS = new String[] { "-XX:+UsePerfData" }; + private static final String JCMD_LIST_REGEX = "^\\d+\\s*.*"; + + public static void main(String[] args) throws Exception { + testJcmdUsage("-h"); + testJcmdUsage("-help"); + testJcmdDefaults(); + testJcmdDefaults("-l"); + } + + /** + * jcmd -J-XX:+UsePerfData -h + * jcmd -J-XX:+UsePerfData -help + */ + private static void testJcmdUsage(String... jcmdArgs) throws Exception { + OutputAnalyzer output = JcmdBase.jcmdNoPid(VM_ARGS, jcmdArgs); + + assertNotEquals(output.getExitValue(), 0); + verifyOutputAgainstFile(output); + } + + /** + * jcmd -J-XX:+UsePerfData + * jcmd -J-XX:+UsePerfData -l + */ + private static void testJcmdDefaults(String... jcmdArgs) throws Exception { + OutputAnalyzer output = JcmdBase.jcmdNoPid(VM_ARGS, jcmdArgs); + + output.shouldHaveExitValue(0); + output.shouldContain("sun.tools.jcmd.JCmd"); + matchListedProcesses(output); + } + + /** + * Verifies the listed processes match a certain pattern. + * + * The output should look like: + * 12246 sun.tools.jcmd.JCmd + * 24428 com.sun.javatest.regtest.MainWrapper /tmp/jtreg/jtreg-workdir/classes/sun/tools/jcmd/TestJcmdDefaults.jta + * + * @param output The generated output from the jcmd. + * @throws Exception + */ + private static void matchListedProcesses(OutputAnalyzer output) throws Exception { + int matchedCount = output.shouldMatchByLine(JCMD_LIST_REGEX); + assertGreaterThan(matchedCount , 0, + "Found no lines matching pattern: " + JCMD_LIST_REGEX); + } + + private static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { + File file = new File(TEST_SRC, "usage.out"); + List fileOutput = Utils.fileAsList(file); + List outputAsLines = output.asLines(); + assertTrue(outputAsLines.containsAll(fileOutput), + "The ouput should contain all content of " + file.getAbsolutePath()); + } + +} diff --git a/test/sun/tools/jcmd/TestJcmdSanity.java b/test/sun/tools/jcmd/TestJcmdSanity.java new file mode 100644 index 0000000000000000000000000000000000000000..b25c4c54786b1fe7dbb8d5ad0cf5ae0ade27b878 --- /dev/null +++ b/test/sun/tools/jcmd/TestJcmdSanity.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.testlibrary.Asserts.*; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import jdk.testlibrary.JcmdBase; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; + +/** + * Unit test for jcmd utility. The test will send different diagnostic command + * requests to the current java process. + */ +/* + * @test + * @bug 7104647 7154822 + * @library /lib/testlibrary + * @run main TestJcmdSanity + */ +public class TestJcmdSanity { + + private static final String TEST_SRC = System.getProperty("test.src").trim(); + private static final String[] VM_ARGS = new String[] { "-XX:+UsePerfData" }; + private static final String JCMD_COMMAND_REGEX = "(\\w|\\.)*"; + private static final String PERF_COUNTER_REGEX = "(\\w|\\.)*\\=.*"; + + public static void main(String[] args) throws Exception { + testJcmdPidHelp(); + testJcmdPidHelpHelp(); + testJcmdPid_f(); + testJcmdPidPerfCounterPrint(); + testJcmdPidBigScript(); + } + + /** + * jcmd -J-XX:+UsePerfData pid help + */ + private static void testJcmdPidHelp() throws Exception { + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"help"}); + output.shouldHaveExitValue(0); + output.shouldNotContain("Exception"); + output.shouldContain(Integer.toString(ProcessTools.getProcessId()) + ":"); + matchJcmdCommands(output); + output.shouldContain("For more information about a specific command use 'help '."); + } + + /** + * jcmd -J-XX:+UsePerfData pid help help + */ + private static void testJcmdPidHelpHelp() throws Exception { + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"help", "help"}); + + output.shouldHaveExitValue(0); + verifyOutputAgainstFile(output); + } + + /** + * jcmd -J-XX:+UsePerfData pid PerfCounter.print + */ + private static void testJcmdPidPerfCounterPrint() throws Exception { + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"PerfCounter.print"}); + + output.shouldHaveExitValue(0); + matchPerfCounters(output); + } + + /** + * jcmd -J-XX:+UsePerfData pid -f dcmd-script.txt + */ + private static void testJcmdPid_f() throws Exception { + File scrpitFile = new File(TEST_SRC, "dcmd-script.txt"); + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"-f", scrpitFile.getAbsolutePath()}); + + output.shouldHaveExitValue(0); + verifyOutputAgainstFile(output); + } + + /** + * Tests that it possible send a file over 1024 bytes large via jcmd -f. + * + * jcmd -J-XX:+UsePerfData pid -f dcmd-big-script.txt + */ + private static void testJcmdPidBigScript() throws Exception { + File scrpitFile = new File(TEST_SRC, "dcmd-big-script.txt"); + OutputAnalyzer output = JcmdBase.jcmd(VM_ARGS, + new String[] {"-f", scrpitFile.getAbsolutePath()}); + + output.shouldHaveExitValue(0); + output.shouldNotContain("Exception"); + output.shouldContain(System.getProperty("java.vm.name").trim()); + } + + /** + * Verifies the listed jcmd commands match a certain pattern. + * + * The output of the jcmd commands should look like: + * VM.uptime + * VM.flags + * VM.system_properties + * + * @param output The generated output from the jcmd. + * @throws Exception + */ + private static void matchJcmdCommands(OutputAnalyzer output) throws Exception { + int matchedCount = output.shouldMatchByLine(JCMD_COMMAND_REGEX, + "help", + JCMD_COMMAND_REGEX); + assertGreaterThan(matchedCount , 0, + "Found no lines matching pattern: " + JCMD_COMMAND_REGEX); + } + + /** + * Verifies the generated output from the PerfCounter.print command + * matches a certain pattern. + * + * The output of perf counters should look like: + * java.property.java.vm.name="Java HotSpot(TM) 64-Bit Server VM" + * java.threads.daemon=7 + * sun.rt.javaCommand="com.sun.javatest.regtest.MainWrapper /tmp/jtreg/jtreg-workdir/classes/sun/tools/jcmd/TestJcmdSanity.jta" + * + * @param output The generated output from the PerfCounter.print command. + * @throws Exception + */ + private static void matchPerfCounters(OutputAnalyzer output) throws Exception { + int matchedCount = output.shouldMatchByLineFrom(PERF_COUNTER_REGEX, + PERF_COUNTER_REGEX); + assertGreaterThan(matchedCount , 0, + "Found no lines matching pattern: " + PERF_COUNTER_REGEX); + } + + private static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { + File file = new File(TEST_SRC, "help_help.out"); + List fileOutput = Utils.fileAsList(file); + List outputAsLines = output.asLines(); + assertTrue(outputAsLines.containsAll(fileOutput), + "The ouput should contain all content of " + file.getAbsolutePath()); + } + +} diff --git a/test/sun/tools/jcmd/help_help.out b/test/sun/tools/jcmd/help_help.out index beaf0f35b94581516e25f0755ea0798db1102281..3f151b92acd6d9999a13cd31e03083ca68583473 100644 --- a/test/sun/tools/jcmd/help_help.out +++ b/test/sun/tools/jcmd/help_help.out @@ -1,7 +1,7 @@ help For more information about a specific command use 'help '. With no argument this will show a list of available commands. 'help all' will show help for all commands. -Impact: Low +Impact: Low Syntax : help [options] [] diff --git a/test/sun/tools/jcmd/jcmd-Defaults.sh b/test/sun/tools/jcmd/jcmd-Defaults.sh deleted file mode 100644 index 2d6aa2ebe893a05bcf064e98baa1bd3aed9ec3e0..0000000000000000000000000000000000000000 --- a/test/sun/tools/jcmd/jcmd-Defaults.sh +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2011, 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. -# - -# @test -# @bug 7104647 -# @run shell jcmd-Defaults.sh -# @summary Test that output of 'jcmd' and 'jcmd -l' match a specific pattern - -JCMD="${TESTJAVA}/bin/jcmd" - -${JCMD} -J-XX:+UsePerfData 2>&1 | awk -f ${TESTSRC}/jcmd_Output1.awk - -${JCMD} -J-XX:+UsePerfData -l 2>&1 | awk -f ${TESTSRC}/jcmd_Output1.awk diff --git a/test/sun/tools/jcmd/jcmd-big-script.sh b/test/sun/tools/jcmd/jcmd-big-script.sh deleted file mode 100644 index a101c8cf2a8fe8db3c646b4b2869554f18779023..0000000000000000000000000000000000000000 --- a/test/sun/tools/jcmd/jcmd-big-script.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# @test -# @bug 7154822 -# @summary test if we can send a file over 1024 bytes large via jcmd -f -# @author David Buck -# -# @library ../common -# @build SimpleApplication ShutdownSimpleApplication -# @run shell jcmd-big-script.sh - -. ${TESTSRC}/../common/CommonSetup.sh -. ${TESTSRC}/../common/ApplicationSetup.sh - -# Start application and use PORTFILE for coordination -PORTFILE="${TESTCLASSES}"/shutdown.port -startApplication SimpleApplication "${PORTFILE}" - -failed=0; - -# -f