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.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.List; 34 35 import jdk.testlibrary.Asserts; 36 import jdk.testlibrary.JDKToolLauncher; 37 import jdk.testlibrary.OutputAnalyzer; 38 import jdk.testlibrary.Utils; 39 40 /** 41 * The helper class for running jps utility and verifying output from it 42 */ 43 public final class JpsHelper { 44 45 /** 46 * Helper class for handling jps arguments 47 */ 48 public enum JpsArg { 49 q, 50 l, 51 m, 52 v, 53 V; 54 55 /** 56 * Generate all possible combinations of {@link JpsArg} 57 * (31 argument combinations and no arguments case) 58 */ 59 public static List<List<JpsArg>> generateCombinations() { 60 final int argCount = JpsArg.values().length; 61 // If there are more than 30 args this algorithm will overflow. 62 Asserts.assertLessThan(argCount, 31, "Too many args"); 63 64 List<List<JpsArg>> combinations = new ArrayList<>(); 65 int combinationCount = (int) Math.pow(2, argCount); 66 for (int currCombo = 0; currCombo < combinationCount; ++currCombo) { 67 List<JpsArg> combination = new ArrayList<>(); 68 for (int position = 0; position < argCount; ++position) { 69 int bit = 1 << position; 70 if ((bit & currCombo) != 0) { 71 combination.add(JpsArg.values()[position]); 72 } 73 } 74 combinations.add(combination); 75 } 76 return combinations; 77 } 78 79 /** 80 * Return combination of {@link JpsArg} as a String array 81 */ 82 public static String[] asCmdArray(List<JpsArg> jpsArgs) { 83 List<String> list = new ArrayList<>(); 84 for (JpsArg jpsArg : jpsArgs) { 85 list.add("-" + jpsArg.toString()); 86 } 87 return list.toArray(new String[list.size()]); 88 } 89 90 } 91 92 /** 93 * VM arguments to start test application with 94 */ 95 public static final String[] VM_ARGS = {"-Xmx512m", "-XX:+PrintGCDetails"}; 96 /** 97 * VM flag to start test application with 98 */ 99 public static final String VM_FLAG = "+DisableExplicitGC"; 100 101 private static File vmFlagsFile = null; 102 private static List<String> testVmArgs = null; 103 private static File manifestFile = null; 104 105 /** 106 * Create a file containing VM_FLAG in the working directory 107 */ 108 public static File getVmFlagsFile() throws IOException { 109 if (vmFlagsFile == null) { 110 vmFlagsFile = new File("vmflags"); 111 try (BufferedWriter output = new BufferedWriter(new FileWriter(vmFlagsFile))) { 112 output.write(VM_FLAG); 113 } 114 vmFlagsFile.deleteOnExit(); 115 } 116 return vmFlagsFile; 117 } 118 119 /** 120 * Return a list of VM arguments 121 */ 122 public static List<String> getVmArgs() throws IOException { 123 if (testVmArgs == null) { 124 testVmArgs = new ArrayList<>(); 125 testVmArgs.addAll(Arrays.asList(VM_ARGS)); 126 testVmArgs.add("-XX:Flags=" + getVmFlagsFile().getAbsolutePath()); 127 } 128 return testVmArgs; 129 } 130 131 /** 132 * Start jps utility without any arguments 133 */ 134 public static OutputAnalyzer jps() throws Exception { 135 return jps(null, null); 136 } 137 138 /** 139 * Start jps utility with tool arguments 140 */ 141 public static OutputAnalyzer jps(String... toolArgs) throws Exception { 142 return jps(null, Arrays.asList(toolArgs)); 143 } 144 145 /** 146 * Start jps utility with VM args and tool arguments 147 */ 148 public static OutputAnalyzer jps(List<String> vmArgs, List<String> toolArgs) throws Exception { 149 JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps"); 150 if (vmArgs != null) { 151 for (String vmArg : vmArgs) { 152 launcher.addVMArg(vmArg); 153 } 154 } 155 if (toolArgs != null) { 156 for (String toolArg : toolArgs) { 157 launcher.addToolArg(toolArg); 158 } 159 } 160 161 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); 162 System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); 163 OutputAnalyzer output = new OutputAnalyzer(processBuilder.start()); 164 System.out.println(output.getOutput()); 165 166 return output; 167 } 168 169 /** 170 * Verify jps output contains pids and programs' name information. 171 * The function will discard any lines that come before the first line with pid. 172 * This can happen if the JVM outputs a warning message for some reason 173 * before running jps. 174 * 175 * The output can look like: 176 * 35536 Jps 177 * 35417 Main 178 * 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar 179 */ 180 public static void verifyJpsOutput(OutputAnalyzer output, String regex) throws Exception { 181 output.shouldHaveExitValue(0); 182 int matchedCount = output.shouldMatchByLineFrom(regex, regex); 183 assertGreaterThan(matchedCount , 0, "Found no lines matching pattern: " + regex); 184 } 185 186 /** 187 * Compare jps output with a content in a file line by line 188 */ 189 public static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { 190 String testSrc = System.getProperty("test.src", "?"); 191 File file = new File(testSrc, "usage.out"); 192 List<String> fileOutput = Utils.fileAsList(file); 193 List<String> outputAsLines = output.asLines(); 194 assertTrue(outputAsLines.containsAll(fileOutput), 195 "The ouput should contain all content of " + file.getAbsolutePath()); 196 } 197 198 private static File getManifest(String className) throws IOException { 199 if (manifestFile == null) { 200 manifestFile = new File(className + ".mf"); 201 try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) { 202 output.write("Main-Class: " + className + Utils.NEW_LINE); 203 } 204 } 205 return manifestFile; 206 } 207 208 /** 209 * Build a jar of test classes in runtime 210 */ 211 public static File buildJar(String className) throws Exception { 212 File jar = new File(className + ".jar"); 213 214 List<String> jarArgs = new ArrayList<>(); 215 jarArgs.add("-cfm"); 216 jarArgs.add(jar.getAbsolutePath()); 217 File manifestFile = getManifest(className); 218 jarArgs.add(manifestFile.getAbsolutePath()); 219 String testClassPath = System.getProperty("test.class.path", "?"); 220 for (String path : testClassPath.split(File.pathSeparator)) { 221 jarArgs.add("-C"); 222 jarArgs.add(path); 223 jarArgs.add("."); 224 } 225 226 System.out.println("Running jar " + jarArgs.toString()); 227 sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); 228 if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) { 229 throw new Exception("jar failed: args=" + jarArgs.toString()); 230 } 231 232 manifestFile.delete(); 233 jar.deleteOnExit(); 234 235 return jar; 236 } 237 238 }