alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (JstatdTest.java)

This example Java source code file (JstatdTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

exception, file, jdktoollauncher, jstatgcutilparser, net, network, outputanalyzer, port, processbuilder, processthread, registry, remoteexception, rmi, start, string, throwable, util, xx\:\+useperfdata

The JstatdTest.java Java example source code

/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.File;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Arrays;

import static jdk.testlibrary.Asserts.*;
import jdk.testlibrary.JDKToolLauncher;
import jdk.testlibrary.OutputAnalyzer;
import jdk.testlibrary.ProcessThread;
import jdk.testlibrary.TestThread;
import jdk.testlibrary.Utils;

/**
 * The base class for tests of jstatd.
 *
 * The test sequence for TestJstatdDefaults for example is:
 * <pre>
 * {@code
 * // start jstatd process
 * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy
 *
 * // run jps and verify its output
 * jps -J-XX:+UsePerfData hostname
 *
 * // run jstat and verify its output
 * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname 250 5
 *
 * // stop jstatd process and verify that no unexpected exceptions have been thrown
 * }
 * </pre>
 */
public final class JstatdTest {

    /**
     * jstat gcutil option: takes JSTAT_GCUTIL_SAMPLES samples at
     * JSTAT_GCUTIL_INTERVAL_MS millisecond intervals
     */
    private static final int JSTAT_GCUTIL_SAMPLES = 5;
    private static final int JSTAT_GCUTIL_INTERVAL_MS = 250;
    private static final String JPS_OUTPUT_REGEX = "^\\d+\\s*.*";

    private boolean useDefaultPort = true;
    private String port;
    private String serverName;
    private String jstatdPid;
    private boolean withExternalRegistry = false;

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    public void setUseDefaultPort(boolean useDefaultPort) {
        this.useDefaultPort = useDefaultPort;
    }

    public void setWithExternalRegistry(boolean withExternalRegistry) {
        this.withExternalRegistry = withExternalRegistry;
    }

    /**
     * Parse pid from jps output
     */
    private String parsePid(String tool, OutputAnalyzer output) throws Exception {
        String[] lines = output.getOutput().split(Utils.NEW_LINE);
        String pid = null;
        int count = 0;
        String processName = tool;
        if (tool == "rmiregistry") {
            processName = "registryimpl";
        }
        for (String line : lines) {
            if (line.toLowerCase().matches("^\\d+\\s{1}" + processName + "$")) {
                pid = line.split(" ")[0];
                count++;
            }
        }
        if (count > 1) {
            throw new Exception("Expected one " + tool
                    + " process, got " + count + ". Test will be canceled.");
        }

        return pid;
    }

    private String getToolPid(String tool)
            throws Exception {
        OutputAnalyzer output = runJps();
        return parsePid(tool, output);
    }

    private String waitOnTool(String tool, TestThread thread) throws Throwable {
        while (true) {
            String pid = getToolPid(tool);

            if (pid != null) {
                System.out.println(tool + " pid: " + pid);
                return pid;
            }

            Throwable t = thread.getUncaught();
            if (t != null) {
                if (t.getMessage().contains(
                        "java.rmi.server.ExportException: Port already in use")) {
                    System.out.println("Port already in use. Trying to restart with a new one...");
                    Thread.sleep(100);
                    return null;
                } else {
                    // Something unexpected has happened
                    throw new Throwable(t);
                }
            }

            System.out.println("Waiting until " + tool + " is running...");
            Thread.sleep(100);
        }
    }

    private void log(String caption, String... cmd) {
        System.out.println(Utils.NEW_LINE + caption + ":");
        System.out.println(Arrays.toString(cmd).replace(",", ""));
    }

    private String getDestination() throws UnknownHostException {
        String option = Utils.getHostname();
        if (port != null) {
            option += ":" + port;
        }
        if (serverName != null) {
            option += "/" + serverName;
        }
        return option;
    }

    /**
     * Depending on test settings command line can look like:
     *
     * jps -J-XX:+UsePerfData hostname
     * jps -J-XX:+UsePerfData hostname:port
     * jps -J-XX:+UsePerfData hostname/serverName
     * jps -J-XX:+UsePerfData hostname:port/serverName
     */
    private OutputAnalyzer runJps() throws Exception {
        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps");
        launcher.addVMArg("-XX:+UsePerfData");
        launcher.addToolArg(getDestination());

        String[] cmd = launcher.getCommand();
        log("Start jps", cmd);

        ProcessBuilder processBuilder = new ProcessBuilder(cmd);
        OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
        System.out.println(output.getOutput());

        return output;
    }

    /**
     * Verifies output form jps contains pids and programs' name information.
     * The function will discard any lines that come before the first line with pid.
     * This can happen if the JVM outputs a warning message for some reason
     * before running jps.
     *
     * The output can look like:
     * 35536 Jstatd
     * 35417 Main
     * 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar
     */
    private void verifyJpsOutput(OutputAnalyzer output) throws Exception {
        output.shouldHaveExitValue(0);
        assertFalse(output.getOutput().isEmpty(), "Output should not be empty");

        boolean foundFirstLineWithPid = false;
        String[] lines = output.getOutput().split(Utils.NEW_LINE);
        for (String line : lines) {
            if (!foundFirstLineWithPid) {
                foundFirstLineWithPid = line.matches(JPS_OUTPUT_REGEX);
                continue;
            }
            assertTrue(line.matches(JPS_OUTPUT_REGEX),
                    "Output does not match the pattern" + Utils.NEW_LINE + line);
        }
        assertTrue(foundFirstLineWithPid, "Invalid output");
    }

    /**
     * Depending on test settings command line can look like:
     *
     * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname 250 5
     * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname:port 250 5
     * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname/serverName 250 5
     * jstat -J-XX:+UsePerfData -J-Duser.language=en -gcutil pid@hostname:port/serverName 250 5
     */
    private OutputAnalyzer runJstat() throws Exception {
        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstat");
        launcher.addVMArg("-XX:+UsePerfData");
        launcher.addVMArg("-Duser.language=en");
        launcher.addToolArg("-gcutil");
        launcher.addToolArg(jstatdPid + "@" + getDestination());
        launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_INTERVAL_MS));
        launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_SAMPLES));

        String[] cmd = launcher.getCommand();
        log("Start jstat", cmd);

        ProcessBuilder processBuilder = new ProcessBuilder(cmd);
        OutputAnalyzer output = new OutputAnalyzer(processBuilder.start());
        System.out.println(output.getOutput());

        return output;
    }

    private void verifyJstatOutput(OutputAnalyzer output)
            throws Exception {
        output.shouldHaveExitValue(0);
        assertFalse(output.getOutput().isEmpty(), "Output should not be empty");

        JstatGCUtilParser gcUtilParser = new JstatGCUtilParser(
                output.getOutput());
        gcUtilParser.parse(JSTAT_GCUTIL_SAMPLES);
    }

    private void runToolsAndVerify() throws Exception {
        OutputAnalyzer output = runJps();
        verifyJpsOutput(output);

        output = runJstat();
        verifyJstatOutput(output);
    }

    private Registry startRegistry()
            throws InterruptedException, RemoteException {
        Registry registry = null;
        try {
            System.out.println("Start rmiregistry on port " + port);
            registry = LocateRegistry
                    .createRegistry(Integer.parseInt(port));
        } catch (RemoteException e) {
            if (e.getMessage().contains("Port already in use")) {
                System.out.println("Port already in use. Trying to restart with a new one...");
                Thread.sleep(100);
                return null;
            } else {
                throw e;
            }
        }
        return registry;
    }

    private void cleanUpThread(ProcessThread thread) throws Throwable {
        if (thread != null) {
            thread.stopProcess();
            thread.joinAndThrow();
        }
    }

    /**
     * Depending on test settings command line can look like:
     *
     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy
     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port
     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -n serverName
     * jstatd -J-XX:+UsePerfData -J-Djava.security.policy=all.policy -p port -n serverName
     */
    private String[] getJstatdCmd() throws UnknownHostException {
        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstatd");
        launcher.addVMArg("-XX:+UsePerfData");
        String testSrc = System.getProperty("test.src");
        File policy = new File(testSrc, "all.policy");
        assertTrue(policy.exists() && policy.isFile(),
                "Security policy " + policy.getAbsolutePath() + " does not exist or not a file");
        launcher.addVMArg("-Djava.security.policy=" + policy.getAbsolutePath());
        if (port != null) {
            launcher.addToolArg("-p");
            launcher.addToolArg(port);
        }
        if (serverName != null) {
            launcher.addToolArg("-n");
            launcher.addToolArg(serverName);
        }

        String[] cmd = launcher.getCommand();
        log("Start jstatd", cmd);
        return cmd;
    }

    private ProcessThread tryToSetupJstatdProcess() throws Throwable {
        ProcessThread jstatdThread = new ProcessThread("Jstatd-Thread",
                getJstatdCmd());
        try {
            jstatdThread.start();
            // Make sure jstatd is up and running
            jstatdPid = waitOnTool("jstatd", jstatdThread);
            if (jstatdPid == null) {
                // The port is already in use. Cancel and try with new one.
                jstatdThread.stopProcess();
                jstatdThread.join();
                return null;
            }
        } catch (Throwable t) {
            // Something went wrong in the product - clean up!
            cleanUpThread(jstatdThread);
            throw t;
        }

        return jstatdThread;
    }

    public void doTest() throws Throwable {
        ProcessThread jstatdThread = null;
        try {
            while (jstatdThread == null) {
                if (!useDefaultPort || withExternalRegistry) {
                    port = Integer.toString(Utils.getFreePort());
                }

                if (withExternalRegistry) {
                    Registry registry = startRegistry();
                    if (registry == null) {
                        // The port is already in use. Cancel and try with new one.
                        continue;
                    }
                }

                jstatdThread = tryToSetupJstatdProcess();
            }

            runToolsAndVerify();
        } finally {
            cleanUpThread(jstatdThread);
        }

        // Verify output from jstatd
        OutputAnalyzer output = jstatdThread.getOutput();
        assertTrue(output.getOutput().isEmpty(),
                "jstatd should get an empty output, got: "
                + Utils.NEW_LINE + output.getOutput());
        assertNotEquals(output.getExitValue(), 0,
                "jstatd process exited with unexpected exit code");
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java JstatdTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.