1/* 2 * Copyright (c) 2015, 2017, 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/* 25 * @test 26 * @summary Basic test for jhsdb launcher 27 * @library /test/lib 28 * @library /lib/testlibrary 29 * @build jdk.testlibrary.* 30 * @build jdk.test.lib.apps.* 31 * @run main BasicLauncherTest 32 */ 33 34import java.io.BufferedReader; 35import java.io.IOException; 36import java.io.OutputStream; 37import java.io.InputStreamReader; 38import java.util.ArrayList; 39import java.util.List; 40import java.util.Arrays; 41import java.util.Optional; 42import jdk.testlibrary.JDKToolLauncher; 43import jdk.testlibrary.Utils; 44import jdk.testlibrary.OutputAnalyzer; 45import jdk.testlibrary.ProcessTools; 46import jdk.test.lib.apps.LingeredApp; 47import jdk.test.lib.Platform; 48 49public class BasicLauncherTest { 50 51 private static LingeredApp theApp = null; 52 private static boolean useJavaLauncher = false; 53 54 private static JDKToolLauncher createSALauncher() { 55 JDKToolLauncher launcher = null; 56 if (useJavaLauncher) { 57 // Use java launcher if we need to pass additional parameters to VM 58 // for debugging purpose 59 // e.g. -Xlog:class+load=info:file=/tmp/BasicLauncherTest.log 60 launcher = JDKToolLauncher.createUsingTestJDK("java"); 61 launcher.addToolArg("sun.jvm.hotspot.SALauncher"); 62 } 63 else { 64 launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); 65 } 66 67 return launcher; 68 } 69 70 public static void launchCLHSDB() 71 throws IOException { 72 73 System.out.println("Starting LingeredApp"); 74 try { 75 theApp = LingeredApp.startApp(); 76 77 System.out.println("Starting clhsdb against " + theApp.getPid()); 78 JDKToolLauncher launcher = createSALauncher(); 79 launcher.addToolArg("clhsdb"); 80 launcher.addToolArg("--pid=" + Long.toString(theApp.getPid())); 81 82 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); 83 processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); 84 Process toolProcess = processBuilder.start(); 85 86 try (OutputStream out = toolProcess.getOutputStream()) { 87 out.write("universe\n".getBytes()); 88 out.write("quit\n".getBytes()); 89 } 90 91 // By default child process output stream redirected to pipe, so we are reading it in foreground. 92 Exception unexpected = null; 93 try (BufferedReader reader = 94 new BufferedReader(new InputStreamReader(toolProcess.getInputStream()))) { 95 String line; 96 97 while ((line = reader.readLine()) != null) { 98 line = line.trim(); 99 System.out.println(line); 100 101 if (line.contains("unknown subtype of CollectedHeap")) { 102 unexpected = new RuntimeException("CollectedHeap type should be known."); 103 break; 104 } 105 } 106 } 107 108 toolProcess.waitFor(); 109 110 if (toolProcess.exitValue() != 0) { 111 throw new RuntimeException("FAILED CLHSDB terminated with non-zero exit code " + toolProcess.exitValue()); 112 } 113 114 if (unexpected != null) { 115 throw unexpected; 116 } 117 118 } catch (Exception ex) { 119 throw new RuntimeException("Test ERROR " + ex, ex); 120 } finally { 121 LingeredApp.stopApp(theApp); 122 } 123 } 124 125 public static void launchJStack() throws IOException { 126 127 if (Platform.isOSX()) { 128 // Coredump stackwalking is not implemented for Darwin 129 System.out.println("This test is not expected to work on OS X. Skipping"); 130 return; 131 } 132 133 System.out.println("Starting LingeredApp"); 134 try { 135 theApp = LingeredApp.startApp(Arrays.asList("-Xmx256m")); 136 137 System.out.println("Starting jstack against " + theApp.getPid()); 138 JDKToolLauncher launcher = createSALauncher(); 139 140 launcher.addToolArg("jstack"); 141 launcher.addToolArg("--pid=" + Long.toString(theApp.getPid())); 142 143 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); 144 OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);; 145 output.shouldContain("No deadlocks found"); 146 output.shouldNotContain("illegal bci"); 147 output.shouldNotContain("AssertionFailure"); 148 output.shouldHaveExitValue(0); 149 150 } catch (Exception ex) { 151 throw new RuntimeException("Test ERROR " + ex, ex); 152 } finally { 153 LingeredApp.stopApp(theApp); 154 } 155 } 156 157 /** 158 * 159 * @param vmArgs - vm and java arguments to launch test app 160 * @return exit code of tool 161 */ 162 public static void launch(String expectedMessage, 163 Optional<String> unexpectedMessage, List<String> toolArgs) 164 throws IOException { 165 166 System.out.println("Starting LingeredApp"); 167 try { 168 theApp = LingeredApp.startApp(Arrays.asList("-Xmx256m")); 169 170 System.out.println("Starting " + toolArgs.get(0) + " against " + theApp.getPid()); 171 JDKToolLauncher launcher = createSALauncher(); 172 173 for (String cmd : toolArgs) { 174 launcher.addToolArg(cmd); 175 } 176 177 launcher.addToolArg("--pid=" + Long.toString(theApp.getPid())); 178 179 ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); 180 processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); 181 OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);; 182 output.shouldContain(expectedMessage); 183 unexpectedMessage.ifPresent(output::shouldNotContain); 184 output.shouldHaveExitValue(0); 185 186 } catch (Exception ex) { 187 throw new RuntimeException("Test ERROR " + ex, ex); 188 } finally { 189 LingeredApp.stopApp(theApp); 190 } 191 } 192 193 public static void launch(String expectedMessage, 194 String unexpectedMessage, String... toolArgs) 195 throws IOException { 196 197 launch(expectedMessage, Optional.ofNullable(unexpectedMessage), 198 Arrays.asList(toolArgs)); 199 } 200 201 public static void main(String[] args) throws Exception { 202 203 if (!Platform.shouldSAAttach()) { 204 // Silently skip the test if we don't have enough permissions to attach 205 System.err.println("Error! Insufficient permissions to attach."); 206 return; 207 } 208 209 launchCLHSDB(); 210 211 launch("compiler detected", null, "jmap", "--clstats"); 212 launchJStack(); 213 launch("compiler detected", null, "jmap"); 214 launch("Java System Properties", 215 "System Properties info not available", "jinfo"); 216 launch("java.threads", null, "jsnap"); 217 218 // The test throws RuntimeException on error. 219 // IOException is thrown if LingeredApp can't start because of some bad 220 // environment condition 221 System.out.println("Test PASSED"); 222 } 223} 224