1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import static jdk.testlibrary.Asserts.assertGreaterThan; 25 import static jdk.testlibrary.Asserts.assertTrue; 26 27 import java.io.BufferedWriter; 28 import java.io.File; 29 import java.io.FileWriter; 30 import java.io.IOException; 31 import java.nio.file.Files; 32 import java.nio.file.Path; 33 import java.nio.file.Paths; 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.List; 37 38 import jdk.testlibrary.Asserts; 39 import jdk.testlibrary.JDKToolLauncher; 40 import jdk.testlibrary.OutputAnalyzer; 41 import jdk.testlibrary.Utils; 42 import jdk.testlibrary.ProcessTools; 43 44 /** 45 * The helper class for running jps utility and verifying output from it 46 */ 47 public final class JpsHelper { 48 49 /** 50 * Helper class for handling jps arguments 51 */ 52 public enum JpsArg { 53 q, 54 l, 55 m, 56 v, 57 V; 58 59 /** 60 * Generate all possible combinations of {@link JpsArg} 61 * (31 argument combinations and no arguments case) 62 */ 63 public static List<List<JpsArg>> generateCombinations() { 64 final int argCount = JpsArg.values().length; 65 // If there are more than 30 args this algorithm will overflow. 66 Asserts.assertLessThan(argCount, 31, "Too many args"); 67 68 List<List<JpsArg>> combinations = new ArrayList<>(); 69 int combinationCount = (int) Math.pow(2, argCount); 70 for (int currCombo = 0; currCombo < combinationCount; ++currCombo) { 71 List<JpsArg> combination = new ArrayList<>(); 72 for (int position = 0; position < argCount; ++position) { 73 int bit = 1 << position; 74 if ((bit & currCombo) != 0) { 75 combination.add(JpsArg.values()[position]); 76 } 77 } 78 combinations.add(combination); 79 } 80 return combinations; 81 } 82 83 /** 84 * Return combination of {@link JpsArg} as a String array 85 */ 86 public static String[] asCmdArray(List<JpsArg> jpsArgs) { 87 List<String> list = new ArrayList<>(); 88 for (JpsArg jpsArg : jpsArgs) { 89 list.add("-" + jpsArg.toString()); 90 } 91 return list.toArray(new String[list.size()]); 92 } 93 94 } 95 96 /** 97 * VM arguments to start test application with 98 */ 99 public static final String[] VM_ARGS = {"-Xmx512m", "-XX:+PrintGCDetails"}; 100 /** 101 * VM flag to start test application with 102 */ 103 public static final String VM_FLAG = "+DisableExplicitGC"; 104 105 private static File vmFlagsFile = null; 106 private static List<String> testVmArgs = null; 107 private static File manifestFile = null; 108 109 /** 110 * Create a file containing VM_FLAG in the working directory 111 */ 112 public static File getVmFlagsFile() throws IOException { 113 if (vmFlagsFile == null) { 114 vmFlagsFile = new File("vmflags"); 115 try (BufferedWriter output = new BufferedWriter(new FileWriter(vmFlagsFile))) { 116 output.write(VM_FLAG); 117 } 118 vmFlagsFile.deleteOnExit(); 119 } 120 return vmFlagsFile; 121 } 122 123 /** 124 * Return a list of VM arguments 125 */ 126 public static List<String> getVmArgs() throws IOException { 127 if (testVmArgs == null) { 128 testVmArgs = new ArrayList<>(); 129 testVmArgs.addAll(Arrays.asList(VM_ARGS)); 130 testVmArgs.add("-XX:Flags=" + getVmFlagsFile().getAbsolutePath()); 131 } 132 return testVmArgs; 133 } 134 135 /** 136 * Start jps utility without any arguments 137 */ 138 public static OutputAnalyzer jps() throws Exception { 139 return jps(null, null); 140 } 141 142 /** 143 * Start jps utility with tool arguments 144 */ 145 public static OutputAnalyzer jps(String... toolArgs) throws Exception { 146 return jps(null, Arrays.asList(toolArgs)); 147 } 148 149 /** 150 * Start jps utility with VM args and tool arguments 151 */ 152 public static OutputAnalyzer jps(List<String> vmArgs, List<String> toolArgs) throws Exception { 153 JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps"); 154 launcher.addVMArg("-XX:+UsePerfData"); 155 if (vmArgs != null) { 156 for (String vmArg : vmArgs) { 157 launcher.addVMArg(vmArg); 158 } 159 } 160 if (toolArgs != null) { 161 for (String toolArg : toolArgs) { 162 launcher.addToolArg(toolArg); 163 } 164 } 165 166 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); 167 System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); 168 OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); 169 System.out.println(output.getOutput()); 170 171 return output; 172 } 173 174 /** 175 * Verify jps stdout contains only pids and programs' name information. 176 * jps stderr may contain VM warning messages which will be ignored. 177 * 178 * The output can look like: 179 * 35536 Jps 180 * 35417 Main 181 * 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar 182 */ 183 public static void verifyJpsOutput(OutputAnalyzer output, String regex) throws Exception { 184 output.shouldHaveExitValue(0); 185 int matchedCount = output.stdoutShouldMatchByLine(regex); 186 assertGreaterThan(matchedCount , 0, "Found no lines matching pattern: " + regex); 187 output.stderrShouldNotMatch("[E|e]xception"); 188 output.stderrShouldNotMatch("[E|e]rror"); 189 } 190 191 /** 192 * Compare jps output with a content in a file line by line 193 */ 194 public static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { 195 String testSrc = System.getProperty("test.src", "?"); 196 Path path = Paths.get(testSrc, "usage.out"); 197 List<String> fileOutput = Files.readAllLines(path); 198 List<String> outputAsLines = output.asLines(); 199 assertTrue(outputAsLines.containsAll(fileOutput), 200 "The ouput should contain all content of " + path.toAbsolutePath()); 201 } 202 203 private static File getManifest(String className) throws IOException { 204 if (manifestFile == null) { 205 manifestFile = new File(className + ".mf"); 206 try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) { 207 output.write("Main-Class: " + className + Utils.NEW_LINE); 208 } 209 } 210 return manifestFile; 211 } 212 213 /** 214 * Build a jar of test classes in runtime 215 */ 216 public static File buildJar(String className) throws Exception { 217 File jar = new File(className + ".jar"); 218 219 List<String> jarArgs = new ArrayList<>(); 220 jarArgs.add("-cfm"); 221 jarArgs.add(jar.getAbsolutePath()); 222 File manifestFile = getManifest(className); 223 jarArgs.add(manifestFile.getAbsolutePath()); 224 String testClassPath = System.getProperty("test.class.path", "?"); 225 for (String path : testClassPath.split(File.pathSeparator)) { 226 jarArgs.add("-C"); 227 jarArgs.add(path); 228 jarArgs.add("."); 229 } 230 231 System.out.println("Running jar " + jarArgs.toString()); 232 sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); 233 if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) { 234 throw new Exception("jar failed: args=" + jarArgs.toString()); 235 } 236 237 manifestFile.delete(); 238 jar.deleteOnExit(); 239 240 return jar; 241 } 242 243 }