Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/tools/jstatd/JstatdTest.java
38838 views
/*1* Copyright (c) 2013, 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.File;24import java.net.UnknownHostException;25import java.rmi.RemoteException;26import java.rmi.registry.LocateRegistry;27import java.rmi.registry.Registry;28import java.util.Arrays;29import java.util.regex.Pattern;3031import static jdk.testlibrary.Asserts.*;32import jdk.testlibrary.JDKToolLauncher;33import jdk.testlibrary.OutputAnalyzer;34import jdk.testlibrary.ProcessThread;35import jdk.testlibrary.TestThread;36import jdk.testlibrary.Utils;37import jdk.testlibrary.ProcessTools;3839/**40* The base class for tests of jstatd.41*42* The test sequence for TestJstatdDefaults for example is:43* <pre>44* {@code45* // start jstatd process46* jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy47*48* // run jps and verify its output49* jps -J-XX:+UsePerfData hostname50*51* // run jstat and verify its output52* jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname 250 553*54* // stop jstatd process and verify that no unexpected exceptions have been thrown55* }56* </pre>57*/58public final class JstatdTest {5960/**61* jstat gcutil option: takes JSTAT_GCUTIL_SAMPLES samples at62* JSTAT_GCUTIL_INTERVAL_MS millisecond intervals63*/64private static final int JSTAT_GCUTIL_SAMPLES = 5;65private static final int JSTAT_GCUTIL_INTERVAL_MS = 250;66private static final String JPS_OUTPUT_REGEX = "^\\d+\\s*.*";6768private boolean useDefaultPort = true;69private String port;70private String serverName;71private String jstatdPid;72private boolean withExternalRegistry = false;7374public void setServerName(String serverName) {75this.serverName = serverName;76}7778public void setUseDefaultPort(boolean useDefaultPort) {79this.useDefaultPort = useDefaultPort;80}8182public void setWithExternalRegistry(boolean withExternalRegistry) {83this.withExternalRegistry = withExternalRegistry;84}8586/**87* Parse pid from jps output88*/89private String parsePid(String tool, OutputAnalyzer output) throws Exception {90String[] lines = output.getOutput().split(Utils.NEW_LINE);91String pid = null;92int count = 0;93String processName = tool;94if (tool == "rmiregistry") {95processName = "registryimpl";96}9798Pattern toolInJpsPattern =99Pattern.compile("^\\d+\\s{1}" + processName + "\\s{1}.*-dparent\\.pid\\." + ProcessTools.getProcessId() + ".*");100for (String line : lines) {101if (toolInJpsPattern.matcher(line.toLowerCase()).matches()) {102pid = line.split(" ")[0];103count++;104}105}106if (count > 1) {107throw new Exception("Expected one " + tool108+ " process, got " + count + ". Test will be canceled.");109}110111return pid;112}113114private String getToolPid(String tool)115throws Exception {116OutputAnalyzer output = runJps();117return parsePid(tool, output);118}119120private String waitOnTool(String tool, TestThread thread) throws Throwable {121while (true) {122String pid = getToolPid(tool);123124if (pid != null) {125System.out.println(tool + " pid: " + pid);126return pid;127}128129Throwable t = thread.getUncaught();130if (t != null) {131if (t.getMessage().contains(132"java.rmi.server.ExportException: Port already in use")) {133System.out.println("Port already in use. Trying to restart with a new one...");134Thread.sleep(100);135return null;136} else {137// Something unexpected has happened138throw new Throwable(t);139}140}141142System.out.println("Waiting until " + tool + " is running...");143Thread.sleep(100);144}145}146147private void log(String caption, String... cmd) {148System.out.println(Utils.NEW_LINE + caption + ":");149System.out.println(Arrays.toString(cmd).replace(",", ""));150}151152private String getDestination() throws UnknownHostException {153String option = Utils.getHostname();154if (port != null) {155option += ":" + port;156}157if (serverName != null) {158option += "/" + serverName;159}160return option;161}162163/**164* Depending on test settings command line can look like:165*166* jps -J-XX:+UsePerfData hostname167* jps -J-XX:+UsePerfData hostname:port168* jps -J-XX:+UsePerfData hostname/serverName169* jps -J-XX:+UsePerfData hostname:port/serverName170*/171private OutputAnalyzer runJps() throws Exception {172JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps");173launcher.addVMArg("-XX:+UsePerfData");174// Run jps with -v flag to obtain -Dparent.pid.<pid>175launcher.addToolArg("-v");176launcher.addToolArg(getDestination());177178String[] cmd = launcher.getCommand();179log("Start jps", cmd);180181ProcessBuilder processBuilder = new ProcessBuilder(cmd);182OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());183System.out.println(output.getOutput());184185return output;186}187188/**189* Verifies output form jps contains pids and programs' name information.190* The function will discard any lines that come before the first line with pid.191* This can happen if the JVM outputs a warning message for some reason192* before running jps.193*194* The output can look like:195* 35536 Jstatd196* 35417 Main197* 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar198*/199private void verifyJpsOutput(OutputAnalyzer output) throws Exception {200output.shouldHaveExitValue(0);201assertFalse(output.getOutput().isEmpty(), "Output should not be empty");202203boolean foundFirstLineWithPid = false;204String[] lines = output.getOutput().split(Utils.NEW_LINE);205for (String line : lines) {206if (!foundFirstLineWithPid) {207foundFirstLineWithPid = line.matches(JPS_OUTPUT_REGEX);208continue;209}210assertTrue(line.matches(JPS_OUTPUT_REGEX),211"Output does not match the pattern" + Utils.NEW_LINE + line);212}213assertTrue(foundFirstLineWithPid, "Invalid output");214}215216/**217* Depending on test settings command line can look like:218*219* jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname 250 5220* jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname:port 250 5221* jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname/serverName 250 5222* jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname:port/serverName 250 5223*/224private OutputAnalyzer runJstat() throws Exception {225JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstat");226launcher.addVMArg("-XX:+UsePerfData");227launcher.addVMArg("-Duser.language=en");228launcher.addToolArg("-gcutil");229launcher.addToolArg(jstatdPid + "@" + getDestination());230launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_INTERVAL_MS));231launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_SAMPLES));232233String[] cmd = launcher.getCommand();234log("Start jstat", cmd);235236ProcessBuilder processBuilder = new ProcessBuilder(cmd);237OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());238System.out.println(output.getOutput());239240return output;241}242243private void verifyJstatOutput(OutputAnalyzer output)244throws Exception {245output.shouldHaveExitValue(0);246assertFalse(output.getOutput().isEmpty(), "Output should not be empty");247248JstatGCUtilParser gcUtilParser = new JstatGCUtilParser(249output.getOutput());250gcUtilParser.parse(JSTAT_GCUTIL_SAMPLES);251}252253private void runToolsAndVerify() throws Exception {254OutputAnalyzer output = runJps();255verifyJpsOutput(output);256257output = runJstat();258verifyJstatOutput(output);259}260261private Registry startRegistry()262throws InterruptedException, RemoteException {263Registry registry = null;264try {265System.out.println("Start rmiregistry on port " + port);266registry = LocateRegistry267.createRegistry(Integer.parseInt(port));268} catch (RemoteException e) {269if (e.getMessage().contains("Port already in use")) {270System.out.println("Port already in use. Trying to restart with a new one...");271Thread.sleep(100);272return null;273} else {274throw e;275}276}277return registry;278}279280private void cleanUpThread(ProcessThread thread) throws Throwable {281if (thread != null) {282thread.stopProcess();283thread.joinAndThrow();284}285}286287/**288* Depending on test settings command line can look like:289*290* jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy291* jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port292* jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -n serverName293* jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port -n serverName294*/295private String[] getJstatdCmd() throws Exception {296JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstatd");297launcher.addVMArg("-XX:+UsePerfData");298String testSrc = System.getProperty("test.src");299File policy = new File(testSrc, "all.policy");300assertTrue(policy.exists() && policy.isFile(),301"Security policy " + policy.getAbsolutePath() + " does not exist or not a file");302launcher.addVMArg("-Djava.security.policy=" + policy.getAbsolutePath());303// -Dparent.pid.<pid> will help to identify jstad process started by this test304launcher.addVMArg("-Dparent.pid." + ProcessTools.getProcessId());305if (port != null) {306launcher.addToolArg("-p");307launcher.addToolArg(port);308}309if (serverName != null) {310launcher.addToolArg("-n");311launcher.addToolArg(serverName);312}313314String[] cmd = launcher.getCommand();315log("Start jstatd", cmd);316return cmd;317}318319private ProcessThread tryToSetupJstatdProcess() throws Throwable {320ProcessThread jstatdThread = new ProcessThread("Jstatd-Thread",321getJstatdCmd());322try {323jstatdThread.start();324// Make sure jstatd is up and running325jstatdPid = waitOnTool("jstatd", jstatdThread);326if (jstatdPid == null) {327// The port is already in use. Cancel and try with new one.328jstatdThread.stopProcess();329jstatdThread.join();330return null;331}332} catch (Throwable t) {333// Something went wrong in the product - clean up!334cleanUpThread(jstatdThread);335throw t;336}337338return jstatdThread;339}340341public void doTest() throws Throwable {342ProcessThread jstatdThread = null;343try {344while (jstatdThread == null) {345if (!useDefaultPort || withExternalRegistry) {346port = Integer.toString(Utils.getFreePort());347}348349if (withExternalRegistry) {350Registry registry = startRegistry();351if (registry == null) {352// The port is already in use. Cancel and try with new one.353continue;354}355}356357jstatdThread = tryToSetupJstatdProcess();358}359360runToolsAndVerify();361} finally {362cleanUpThread(jstatdThread);363}364365// Verify output from jstatd366OutputAnalyzer output = jstatdThread.getOutput();367assertTrue(output.getOutput().isEmpty(),368"jstatd should get an empty output, got: "369+ Utils.NEW_LINE + output.getOutput());370assertNotEquals(output.getExitValue(), 0,371"jstatd process exited with unexpected exit code");372}373374}375376377