Path: blob/master/test/jdk/sun/tools/jps/JpsHelper.java
41152 views
/*1* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import static jdk.test.lib.Asserts.assertGreaterThan;24import static jdk.test.lib.Asserts.assertTrue;2526import java.io.BufferedWriter;27import java.io.File;28import java.io.FileWriter;29import java.io.IOException;30import java.nio.file.Files;31import java.nio.file.Path;32import java.nio.file.Paths;33import java.util.ArrayList;34import java.util.Arrays;35import java.util.List;3637import jdk.test.lib.JDKToolLauncher;38import jdk.test.lib.process.OutputAnalyzer;39import jdk.test.lib.process.ProcessTools;40import jdk.test.lib.Asserts;41import jdk.test.lib.Utils;4243/**44* The helper class for running jps utility and verifying output from it45*/46public final class JpsHelper {4748/**49* Helper class for handling jps arguments50*/51public enum JpsArg {52q,53l,54m,55v,56V;5758/**59* Generate all possible combinations of {@link JpsArg}60* (31 argument combinations and no arguments case)61*/62public static List<List<JpsArg>> generateCombinations() {63final int argCount = JpsArg.values().length;64// If there are more than 30 args this algorithm will overflow.65Asserts.assertLessThan(argCount, 31, "Too many args");6667List<List<JpsArg>> combinations = new ArrayList<>();68int combinationCount = (int) Math.pow(2, argCount);69for (int currCombo = 0; currCombo < combinationCount; ++currCombo) {70List<JpsArg> combination = new ArrayList<>();71for (int position = 0; position < argCount; ++position) {72int bit = 1 << position;73if ((bit & currCombo) != 0) {74combination.add(JpsArg.values()[position]);75}76}77combinations.add(combination);78}79return combinations;80}8182/**83* Return combination of {@link JpsArg} as a String array84*/85public static String[] asCmdArray(List<JpsArg> jpsArgs) {86List<String> list = new ArrayList<>();87for (JpsArg jpsArg : jpsArgs) {88list.add("-" + jpsArg.toString());89}90return list.toArray(new String[list.size()]);91}9293}9495/**96* VM flag to start test application with97*/98public static final String VM_FLAG = "+DisableExplicitGC";99100private static File vmFlagsFile = null;101/**102* VM arguments to start test application with.103* -XX:+UsePerfData is required for running the tests on embedded platforms.104*/105private static String[] testVmArgs = {106"-XX:+UsePerfData", "-Xmx512m", "-Xlog:gc",107"-Dmultiline.prop=value1\nvalue2\r\nvalue3",108null /* lazily initialized -XX:Flags */};109private static File manifestFile = null;110111/**112* Create a file containing VM_FLAG in the working directory113*/114public static File getVmFlagsFile() throws IOException {115if (vmFlagsFile == null) {116vmFlagsFile = new File("vmflags");117try (BufferedWriter output = new BufferedWriter(new FileWriter(vmFlagsFile))) {118output.write(VM_FLAG);119}120vmFlagsFile.deleteOnExit();121}122return vmFlagsFile;123}124125/**126* Return a list of VM arguments127*/128public static String[] getVmArgs() throws IOException {129if (testVmArgs[testVmArgs.length - 1] == null) {130testVmArgs[testVmArgs.length - 1] = "-XX:Flags=" + getVmFlagsFile().getAbsolutePath();131}132return testVmArgs;133}134135/**136* Start jps utility without any arguments137*/138public static OutputAnalyzer jps() throws Exception {139return jps(null, null);140}141142/**143* Start jps utility with tool arguments144*/145public static OutputAnalyzer jps(String... toolArgs) throws Exception {146return jps(null, Arrays.asList(toolArgs));147}148149/**150* Start jps utility with VM args and tool arguments151*/152public static OutputAnalyzer jps(List<String> vmArgs, List<String> toolArgs) throws Exception {153JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps");154launcher.addVMArgs(Utils.getFilteredTestJavaOpts("-XX:+UsePerfData"));155launcher.addVMArg("-XX:+UsePerfData");156if (vmArgs != null) {157for (String vmArg : vmArgs) {158launcher.addVMArg(vmArg);159}160}161if (toolArgs != null) {162for (String toolArg : toolArgs) {163launcher.addToolArg(toolArg);164}165}166167ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());168System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", ""));169OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);170System.out.println(output.getOutput());171172return output;173}174175/**176* Verify jps stdout contains only pids and programs' name information.177* jps stderr may contain VM warning messages which will be ignored.178*179* The output can look like:180* 35536 Jps181* 35417 Main182* 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar183*/184public static void verifyJpsOutput(OutputAnalyzer output, String regex) {185output.shouldHaveExitValue(0);186output.stdoutShouldMatchByLine(regex);187output.stderrShouldNotMatch("[E|e]xception");188output.stderrShouldNotMatch("[E|e]rror");189}190191/**192* Compare jps output with a content in a file line by line193*/194public static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException {195String testSrc = System.getProperty("test.src", "?");196Path path = Paths.get(testSrc, "usage.out");197List<String> fileOutput = Files.readAllLines(path);198List<String> outputAsLines = output.asLines();199assertTrue(outputAsLines.containsAll(fileOutput),200"The ouput should contain all content of " + path.toAbsolutePath());201}202203public static void runJpsVariants(Long pid, String processName, String fullProcessName, String argument) throws Exception {204System.out.printf("INFO: user.dir: '%s''\n", System.getProperty("user.dir"));205List<List<JpsHelper.JpsArg>> combinations = JpsHelper.JpsArg.generateCombinations();206for (List<JpsHelper.JpsArg> combination : combinations) {207OutputAnalyzer output = JpsHelper.jps(JpsHelper.JpsArg.asCmdArray(combination));208output.shouldHaveExitValue(0);209210boolean isQuiet = false;211boolean isFull = false;212String pattern;213for (JpsHelper.JpsArg jpsArg : combination) {214switch (jpsArg) {215case q:216// If '-q' is specified output should contain only a list of local VM identifiers:217// 30673218isQuiet = true;219JpsHelper.verifyJpsOutput(output, "^\\d+$");220output.shouldContain(Long.toString(pid));221break;222case l:223// If '-l' is specified output should contain the full package name for the application's main class224// or the full path name to the application's JAR file:225// 30673 /tmp/jtreg/jtreg-workdir/scratch/LingeredAppForJps.jar ...226isFull = true;227pattern = "^" + pid + "\\s+" + replaceSpecialChars(fullProcessName) + ".*";228output.shouldMatch(pattern);229break;230case m:231// If '-m' is specified output should contain the arguments passed to the main method:232// 30673 LingeredAppForJps lockfilename ...233pattern = "^" + pid + ".*" + replaceSpecialChars(argument) + ".*";234output.shouldMatch(pattern);235break;236case v:237// If '-v' is specified output should contain VM arguments:238// 30673 LingeredAppForJps -Xmx512m -XX:+UseParallelGC -XX:Flags=/tmp/jtreg/jtreg-workdir/scratch/vmflags ...239for (String vmArg : JpsHelper.getVmArgs()) {240pattern = "^" + pid + ".*" + replaceSpecialChars(vmArg) + ".*";241output.shouldMatch(pattern);242}243break;244case V:245// If '-V' is specified output should contain VM flags:246// 30673 LingeredAppForJps +DisableExplicitGC ...247pattern = "^" + pid + ".*" + replaceSpecialChars(JpsHelper.VM_FLAG) + ".*";248output.shouldMatch(pattern);249break;250}251252if (isQuiet) {253break;254}255}256257if (!isQuiet) {258// Verify output line by line.259// Output should only contain lines with pids after the first line with pid.260JpsHelper.verifyJpsOutput(output, "^\\d+\\s+.*");261if (!isFull) {262pattern = "^" + pid + "\\s+" + replaceSpecialChars(processName);263if (combination.isEmpty()) {264// If no arguments are specified output should only contain265// pid and process name266pattern += "$";267} else {268pattern += ".*";269}270output.shouldMatch(pattern);271}272}273}274}275276private static String replaceSpecialChars(String str) {277String tmp = str.replace("\\", "\\\\");278tmp = tmp.replace("+", "\\+");279tmp = tmp.replace(".", "\\.");280tmp = tmp.replace("\n", "\\\\n");281tmp = tmp.replace("\r", "\\\\r");282return tmp;283}284}285286287