blob: 563e0698479fcf7834af3612abbed38817128b62 [file] [log] [blame]
/*
* Copyright (c) 2021, 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.io.IOException;
import java.util.ArrayList;
import java.util.List;
import jdk.test.lib.apps.LingeredApp;
import jdk.test.lib.dcmd.CommandExecutorException;
import jdk.test.lib.dcmd.PidJcmdExecutor;
import jdk.test.lib.process.OutputAnalyzer;
import jtreg.SkippedException;
import sun.hotspot.WhiteBox;
public abstract class JCmdTestDumpBase {
private static boolean isStatic; // set first in subclass for dump type
protected static void setIsStatic(boolean value) {
isStatic = value;
}
/**************************************
* for a subclass to do static dump
* public class JCmdTestStaticDump extends JCmdTestDumpBase {
* public static void test() throws Exception {
* setIsStatic(true);
* // do test
* }
* public static void main(String[] args) throws Exception {
* runTest(JCmdTestStaticDump::test);
* }
* }
***************************************/
public static interface JCmdTest {
public void run() throws Exception;
}
public static void runTest(JCmdTest t) throws Exception {
checkCDSEnabled();
t.run();
}
private static final String TEST_CLASSES[] =
{"JCmdTestLingeredApp",
"jdk/test/lib/apps/LingeredApp",
"jdk/test/lib/apps/LingeredApp$1"};
private static final String BOOT_CLASSES[] = {"Hello"};
protected static String testJar = null;
protected static String bootJar = null;
protected static String allJars = null;
public static final boolean useBoot = true;
public static final boolean noBoot = !useBoot;
public static final boolean EXPECT_PASS = true;
public static final boolean EXPECT_FAIL = !EXPECT_PASS;
// If delete the created archive after test.
private static boolean keepArchive = false;
public static void setKeepArchive(boolean v) { keepArchive = v; }
public static void checkFileExistence(String fileName, boolean checkExist) throws Exception {
File file = new File(fileName);
boolean exist = file.exists();
boolean resultIsTrue = checkExist ? exist : !exist;
if (!resultIsTrue) {
throw new RuntimeException("File " + fileName + " should " + (checkExist ? "exist" : "not exist"));
}
}
protected static void buildJars() throws Exception {
testJar = JarBuilder.build("test", TEST_CLASSES);
bootJar = JarBuilder.build("boot", BOOT_CLASSES);
System.out.println("Jar file created: " + testJar);
System.out.println("Jar file created: " + bootJar);
allJars = testJar + File.pathSeparator + bootJar;
}
private static void checkCDSEnabled() throws Exception {
boolean cdsEnabled = WhiteBox.getWhiteBox().getBooleanVMFlag("UseSharedSpaces");
if (!cdsEnabled) {
throw new SkippedException("CDS is not available for this JDK.");
}
}
private static boolean argsContain(String[] args, String flag) {
for (String s: args) {
if (s.contains(flag)) {
return true;
}
}
return false;
}
private static boolean argsContainOpts(String[] args, String... opts) {
boolean allIn = true;
for (String f : opts) {
allIn &= argsContain(args, f);
if (!allIn) {
break;
}
}
return allIn;
}
protected static LingeredApp createLingeredApp(String... args) throws Exception {
JCmdTestLingeredApp app = new JCmdTestLingeredApp();
try {
LingeredApp.startAppExactJvmOpts(app, args);
} catch (Exception e) {
// Check flags used.
if (argsContainOpts(args, new String[] {"-Xshare:off", "-XX:+RecordDynamicDumpInfo"}) ||
argsContainOpts(args, new String[] {"-XX:+RecordDynamicDumpInfo", "-XX:ArchiveClassesAtExit="})) {
// app exit premature due to incompactible args
return null;
}
Process proc = app.getProcess();
if (e instanceof IOException && proc.exitValue() == 0) {
// Process started and exit normally.
return null;
}
throw e;
}
return app;
}
private static int logFileCount = 0;
private static void runWithArchiveFile(String archiveName, boolean useBoot, String... messages) throws Exception {
List<String> args = new ArrayList<String>();
if (useBoot) {
args.add("-Xbootclasspath/a:" + bootJar);
}
args.add("-cp");
if (useBoot) {
args.add(testJar);
} else {
args.add(allJars);
}
args.add("-Xshare:on");
args.add("-XX:SharedArchiveFile=" + archiveName);
args.add("-Xlog:class+load");
LingeredApp app = createLingeredApp(args.toArray(new String[0]));
app.setLogFileName("JCmdTest-Run-" + (isStatic ? "Static.log" : "Dynamic.log.") + (logFileCount++));
app.stopApp();
String output = app.getOutput().getStdout();
if (messages != null) {
for (String msg : messages) {
if (!output.contains(msg)) {
throw new RuntimeException(msg + " missed from output");
}
}
}
}
protected static void test(String fileName, long pid,
boolean useBoot, boolean expectOK, String... messages) throws Exception {
System.out.println("Expected: " + (expectOK ? "SUCCESS" : "FAIL"));
String archiveFileName = fileName != null ? fileName :
("java_pid" + pid + (isStatic ? "_static.jsa" : "_dynamic.jsa"));
File archiveFile = new File(archiveFileName);
String jcmd = "VM.cds " + (isStatic ? "static_dump" : "dynamic_dump");
if (archiveFileName != null) {
jcmd += " " + archiveFileName;
}
PidJcmdExecutor cmdExecutor = new PidJcmdExecutor(String.valueOf(pid));
OutputAnalyzer output = cmdExecutor.execute(jcmd, true/*silent*/);
if (expectOK) {
output.shouldHaveExitValue(0);
checkFileExistence(archiveFileName, true);
runWithArchiveFile(archiveFileName, useBoot, messages);
if (!keepArchive) {
archiveFile.delete();
}
} else {
if (!keepArchive) {
checkFileExistence(archiveFileName, false);
}
}
}
protected static void print2ln(String arg) {
System.out.println("\n" + arg + "\n");
}
}