1 /* 2 * Copyright (c) 2014, 2015, 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 * -XX:+UsePerfData is required for running the tests on embedded platforms. 99 */ 100 public static final String[] VM_ARGS = { 101 "-XX:+UsePerfData", "-Xmx512m", "-Xlog:gc*=debug", 102 "-Dmultiline.prop=value1\nvalue2\r\nvalue3" 103 }; 104 /** 105 * VM flag to start test application with 106 */ 107 public static final String VM_FLAG = "+DisableExplicitGC"; 108 109 private static File vmFlagsFile = null; 110 private static List<String> testVmArgs = null; 111 private static File manifestFile = null; 112 113 /** 114 * Create a file containing VM_FLAG in the working directory 115 */ 116 public static File getVmFlagsFile() throws IOException { 117 if (vmFlagsFile == null) { 118 vmFlagsFile = new File("vmflags"); 119 try (BufferedWriter output = new BufferedWriter(new FileWriter(vmFlagsFile))) { 120 output.write(VM_FLAG); 121 } 122 vmFlagsFile.deleteOnExit(); 123 } 124 return vmFlagsFile; 125 } 126 127 /** 128 * Return a list of VM arguments 129 */ 130 public static List<String> getVmArgs() throws IOException { 131 if (testVmArgs == null) { 132 testVmArgs = new ArrayList<>(); 133 testVmArgs.addAll(Arrays.asList(VM_ARGS)); 134 testVmArgs.add("-XX:Flags=" + getVmFlagsFile().getAbsolutePath()); 135 } 136 return testVmArgs; 137 } 138 139 /** 140 * Start jps utility without any arguments 141 */ 142 public static OutputAnalyzer jps() throws Exception { 143 return jps(null, null); 144 } 145 146 /** 147 * Start jps utility with tool arguments 148 */ 149 public static OutputAnalyzer jps(String... toolArgs) throws Exception { 150 return jps(null, Arrays.asList(toolArgs)); 151 } 152 153 /** 154 * Start jps utility with VM args and tool arguments 155 */ 156 public static OutputAnalyzer jps(List<String> vmArgs, List<String> toolArgs) throws Exception { 157 JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps"); 158 launcher.addVMArg("-XX:+UsePerfData"); 159 if (vmArgs != null) { 160 for (String vmArg : vmArgs) { 161 launcher.addVMArg(vmArg); 162 } 163 } 164 if (toolArgs != null) { 165 for (String toolArg : toolArgs) { 166 launcher.addToolArg(toolArg); 167 } 168 } 169 170 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); 171 System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); 172 OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); 173 System.out.println(output.getOutput()); 174 175 return output; 176 } 177 178 /** 179 * Verify jps stdout contains only pids and programs' name information. 180 * jps stderr may contain VM warning messages which will be ignored. 181 * 182 * The output can look like: 183 * 35536 Jps 184 * 35417 Main 185 * 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar 186 */ 187 public static void verifyJpsOutput(OutputAnalyzer output, String regex) throws Exception { 188 output.shouldHaveExitValue(0); 189 int matchedCount = output.stdoutShouldMatchByLine(regex); 190 assertGreaterThan(matchedCount , 0, "Found no lines matching pattern: " + regex); 191 output.stderrShouldNotMatch("[E|e]xception"); 192 output.stderrShouldNotMatch("[E|e]rror"); 193 } 194 195 /** 196 * Compare jps output with a content in a file line by line 197 */ 198 public static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { 199 String testSrc = System.getProperty("test.src", "?"); 200 Path path = Paths.get(testSrc, "usage.out"); 201 List<String> fileOutput = Files.readAllLines(path); 202 List<String> outputAsLines = output.asLines(); 203 assertTrue(outputAsLines.containsAll(fileOutput), 204 "The ouput should contain all content of " + path.toAbsolutePath()); 205 } 206 207 private static File getManifest(String className) throws IOException { 208 if (manifestFile == null) { 209 manifestFile = new File(className + ".mf"); 210 try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) { 211 output.write("Main-Class: " + className + Utils.NEW_LINE); 212 } 213 } 214 return manifestFile; 215 } 216 217 /** 218 * Build a jar of test classes in runtime 219 */ 220 public static File buildJar(String className) throws Exception { 221 File jar = new File(className + ".jar"); 222 223 List<String> jarArgs = new ArrayList<>(); 224 jarArgs.add("-cfm"); 225 jarArgs.add(jar.getAbsolutePath()); 226 File manifestFile = getManifest(className); 227 jarArgs.add(manifestFile.getAbsolutePath()); 228 String testClassPath = System.getProperty("test.class.path", "?"); 229 for (String path : testClassPath.split(File.pathSeparator)) { 230 jarArgs.add("-C"); 231 jarArgs.add(path); 232 jarArgs.add("."); 233 } 234 235 System.out.println("Running jar " + jarArgs.toString()); 236 sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); 237 if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) { 238 throw new Exception("jar failed: args=" + jarArgs.toString()); 239 } 240 241 manifestFile.delete(); 242 jar.deleteOnExit(); 243 244 return jar; 245 } 246 247 }