Path: blob/master/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java
41152 views
/*1* Copyright (c) 2017, 2021, 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 java.io.IOException;24import java.io.OutputStream;25import java.util.List;26import java.util.Map;2728import jdk.test.lib.Utils;29import jdk.test.lib.JDKToolLauncher;30import jdk.test.lib.JDKToolFinder;31import jdk.test.lib.process.OutputAnalyzer;32import jdk.test.lib.SA.SATestUtils;3334/**35* This is a framework to run 'jhsdb clhsdb' commands.36* See open/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java for37* an example of how to write a test.38*/3940public class ClhsdbLauncher {4142private Process toolProcess;4344public ClhsdbLauncher() {45toolProcess = null;46}4748/**49*50* Launches 'jhsdb clhsdb' and attaches to the Lingered App process.51* @param lingeredAppPid - pid of the Lingered App or one its sub-classes.52*/53private void attach(long lingeredAppPid)54throws IOException {55JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");56launcher.addVMArgs(Utils.getTestJavaOpts());57launcher.addToolArg("clhsdb");58if (lingeredAppPid != -1) {59launcher.addToolArg("--pid=" + Long.toString(lingeredAppPid));60System.out.println("Starting clhsdb against " + lingeredAppPid);61}6263ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);64toolProcess = processBuilder.start();65}6667/**68*69* Launches 'jhsdb clhsdb' and loads a core file.70* @param coreFileName - Name of the corefile to be loaded.71*/72private void loadCore(String coreFileName)73throws IOException {7475JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");76launcher.addVMArgs(Utils.getTestJavaOpts());77launcher.addToolArg("clhsdb");78launcher.addToolArg("--core=" + coreFileName);79launcher.addToolArg("--exe=" + JDKToolFinder.getTestJDKTool("java"));80System.out.println("Starting clhsdb against corefile " + coreFileName +81" and exe " + JDKToolFinder.getTestJDKTool("java"));8283ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());84toolProcess = processBuilder.start();85}8687/**88*89* Runs 'jhsdb clhsdb' commands and checks for expected and unexpected strings.90* @param commands - clhsdb commands to execute.91* @param expectedStrMap - Map of expected strings per command which need to92* be checked in the output of the command.93* @param unExpectedStrMap - Map of unexpected strings per command which should94* not be present in the output of the command.95* @return Output of the commands as a String.96*/97private String runCmd(List<String> commands,98Map<String, List<String>> expectedStrMap,99Map<String, List<String>> unExpectedStrMap)100throws IOException, InterruptedException {101String output;102103if (commands == null) {104throw new RuntimeException("CLHSDB command must be provided\n");105}106107// We want to execute clhsdb "echo" and "verbose" commands before the108// requested commands. We can't just issue these commands separately109// because code below won't work correctly if all executed commands are110// not in the commands list. Since the commands list is immutable, we111// need to allocate a mutable one that we can add the extra commands too.112List<String> savedCommands = commands;113commands = new java.util.LinkedList<String>();114115// Enable echoing of all commands so we see them in the output.116commands.add("echo true");117118// Enable verbose exception tracing so we see the full exception backtrace119// when there is a failure.120commands.add("verbose true");121122// Now add all the original commands after the "echo" and "verbose" commands.123commands.addAll(savedCommands);124125try (OutputStream out = toolProcess.getOutputStream()) {126for (String cmd : commands) {127out.write((cmd + "\n").getBytes());128}129out.write("quit\n".getBytes());130out.flush();131}132133OutputAnalyzer oa = new OutputAnalyzer(toolProcess);134try {135toolProcess.waitFor();136} catch (InterruptedException ie) {137toolProcess.destroyForcibly();138throw new Error("Problem awaiting the child process: " + ie);139}140141oa.shouldHaveExitValue(0);142output = oa.getOutput();143System.out.println("Output: ");144System.out.println(output);145146// -Xcheck:jni might be set via TEST_VM_OPTS. Make sure there are no warnings.147oa.shouldNotMatch("^WARNING: JNI local refs:.*$");148oa.shouldNotMatch("^WARNING in native method:.*$");149// This will detect most SA failures, including during the attach.150oa.shouldNotMatch("^sun.jvm.hotspot.debugger.DebuggerException:.*$");151// This will detect unexpected exceptions, like NPEs and asserts, that are caught152// by sun.jvm.hotspot.CommandProcessor.153oa.shouldNotMatch("^Error: .*$");154155String[] parts = output.split("hsdb>");156for (String cmd : commands) {157int index = commands.indexOf(cmd) + 1;158OutputAnalyzer out = new OutputAnalyzer(parts[index]);159out.shouldNotMatch("Unrecognized command.");160161if (expectedStrMap != null) {162List<String> expectedStr = expectedStrMap.get(cmd);163if (expectedStr != null) {164for (String exp : expectedStr) {165out.shouldMatch(exp);166}167}168}169170if (unExpectedStrMap != null) {171List<String> unExpectedStr = unExpectedStrMap.get(cmd);172if (unExpectedStr != null) {173for (String unExp : unExpectedStr) {174out.shouldNotMatch(unExp);175}176}177}178}179return output;180}181182/**183*184* Launches 'jhsdb clhsdb', attaches to the Lingered App, executes the commands,185* checks for expected and unexpected strings.186* @param lingeredAppPid - pid of the Lingered App or one its sub-classes.187* @param commands - clhsdb commands to execute.188* @param expectedStrMap - Map of expected strings per command which need to189* be checked in the output of the command.190* @param unExpectedStrMap - Map of unexpected strings per command which should191* not be present in the output of the command.192* @return Output of the commands as a String.193*/194public String run(long lingeredAppPid,195List<String> commands,196Map<String, List<String>> expectedStrMap,197Map<String, List<String>> unExpectedStrMap)198throws Exception {199200SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.201attach(lingeredAppPid);202return runCmd(commands, expectedStrMap, unExpectedStrMap);203}204205/**206*207* Launches 'jhsdb clhsdb', loads a core file, executes the commands,208* checks for expected and unexpected strings.209* @param coreFileName - Name of the core file to be debugged.210* @param commands - clhsdb commands to execute.211* @param expectedStrMap - Map of expected strings per command which need to212* be checked in the output of the command.213* @param unExpectedStrMap - Map of unexpected strings per command which should214* not be present in the output of the command.215* @return Output of the commands as a String.216*/217public String runOnCore(String coreFileName,218List<String> commands,219Map<String, List<String>> expectedStrMap,220Map<String, List<String>> unExpectedStrMap)221throws IOException, InterruptedException {222223loadCore(coreFileName);224return runCmd(commands, expectedStrMap, unExpectedStrMap);225}226}227228229