diff --git a/test/functional/RasapiTest/build.xml b/test/functional/RasapiTest/build.xml
new file mode 100644
index 00000000000..5d861530105
--- /dev/null
+++ b/test/functional/RasapiTest/build.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ant build script to generate com.ibm.jvm.ras.tests.jar
+
+
+
+
+ Cleaning build directory ${build.dir}
+
+
+
+
+
+
+
+
+
+
+
+
+ Ant version is ${ant.version}
+ Compiling code to ${build.dir} and packaging ${build.jar.tests} to ${dist.dir}
+
+ ============COMPILER SETTINGS============
+ ===fork: yes
+ ===executable: ${compiler.javac}
+ ===source: ${src.level}
+ ===target: ${target.level}
+ ===debug: on
+ ===destdir: ${build.dir}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/functional/RasapiTest/dummy_src/com/ibm/jvm/Dump.java b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/Dump.java
new file mode 100644
index 00000000000..ea30b27a7ff
--- /dev/null
+++ b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/Dump.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * This class is used to trigger and configure the options used to produce different
+ * types of diagnostic dumps available from the IBM JVM.
+ *
+ * -Xdump must be enabled on the command line or the functions that attempt to cause
+ * dumps to be created or set options will fail with a java.lang.RuntimeException.
+ *
+ * The methods on this class can be used to trigger dumps, configure dump options and
+ * query those options.
+ *
+ * The {@link #JavaDump()}, {@link #SystemDump()}, {@link #HeapDump()} and {@link #SnapDump()}
+ * methods trigger dumps of the given type with no options and no return value.
+ * Although they are not configurable they do provide an easy API to use via reflection
+ * if your code is likely to run on both IBM and non-IBM JVMs and you only need the most
+ * basic ability to create a dump.
+ *
+ * The {@link #javaDumpToFile()}, {@link #systemDumpToFile()}, {@link #heapDumpToFile()} and
+ * {@link #snapDumpToFile()} methods allow a destination file to be optionally specified and
+ * will return the full path of the file that is created.
+ *
+ * The recommended usage of the {@link #javaDumpToFile()}, {@link #systemDumpToFile()},
+ * {@link #heapDumpToFile()} and {@link #snapDumpToFile()}
+ * methods is to call the no argument versions of these calls rather than specifying a file
+ * name as this will trigger a dump to the default location. Your dump file will go to the
+ * default location specified by any -Xdump options given to the JVM at startup time following
+ * the user or administrators preferences.
+ * The location the dump file was written to will be returned as a String so the generated
+ * file can be located.
+ *
+ * The {@link #triggerDump(String)} method offers similar functionality as the DumpToFile() methods
+ * but with the ability to specify any dump options that are meaningful for a dump that occurs
+ * immediately. The options are passed as a String that follows the same format as the option
+ * strings passed to -Xdump on the command line.
+ * For example:
+ *
+ *
triggerDump("java") is equivalent to javaDumpToFile() or javaDumpToFile(null) all three
+ * will cause a javadump to be generated to the default location.
+ *
triggerDump("heap:file=heapdump.phd") is equivalent to heapDumpToFile("heapdump.phd")
+ *
triggerDump("heap:file=heapdump.txt,opts=CLASSIC") allows you to specify the CLASSIC
+ * option to triggerDump and produce a text format heap dump which is not possible through
+ * the *DumpToFile(String filename) or *Dump() methods.
+ *
triggerDump("java:request=exclusive") will trigger a java dump with the request option set
+ * to "exclusive" and any other options, including the file name, taken from the default options
+ * for java dumps
+ *
+ *
+ * The {@link #setDumpOptions(String)} method allows dump options that will cause or change how
+ * a dump occurs for an event in the future to be specified. The options are specified in the
+ * format expected by the -Xdump command line. Not all options can be configured at runtime and
+ * this method will throw an InvalidDumpOption exception if it is passed an option that cannot be set.
+ * For example:
+ *
+ *
setDumpOptions("java") - enable java dumps with the default settings.
+ *
setDumpOptions("java:events=vmstop") - enable java dumps on the vmstop event (this will
+ * occur once when the JVM exits).
+ *
setDumpOptions("none") - disable all dump agents on all events.
+ *
setDumpOptions("heap:none") - disable all heap dump agents on all events.
+ *
setDumpOptions("system:none:events=systhrow,filter=java/lang/OutOfMemoryError") - disable
+ * system dumps on systhrow events for OutOfMemory errors only.
+ *
+ * For full details of dump options see the section on dump agents in the documentation for the IBM JVM.
+ *
+ * The {@link #queryDumpOptions()} method returns a String array containing a snapshot of the currently
+ * configured dump options. Each String is in the format expected by the -Xdump command line
+ * option and setDumpOptions. The Strings can be passed back to setDumpOptions to recreate
+ * the current dump agent configuration at a later time.
+ *
+ * The {@link #resetDumpOptions()} method resets the dump options to the settings specified when the
+ * JVM was started removing any additional configuration done since then.
+ * If you wish to change the dump configuration at runtime and then reset it to an earlier
+ * state that included additional runtime configuration done through this API or JVMTI you should
+ * consider saving the result of queryDumpOptions and then later use {@link #setDumpOptions(String)}
+ * to restore that configuration after a call to setDumpOptions("none") to clear all dump agent
+ * configuration.
+ */
+public class Dump {
+
+ public static void JavaDump() {
+ }
+
+ public static void HeapDump() {
+ }
+
+ public static void SystemDump() {
+ }
+
+ private Dump() {
+ }
+
+ public static void SnapDump() {
+ }
+
+ public static String javaDumpToFile(String fileNamePattern ) throws InvalidDumpOptionException {
+ return null;
+ }
+
+ public static String javaDumpToFile() {
+ return null;
+ }
+
+ public static String heapDumpToFile(String fileNamePattern ) throws InvalidDumpOptionException {
+ return null;
+ }
+
+ public static String heapDumpToFile() {
+ return null;
+ }
+
+
+ public static String systemDumpToFile(String fileNamePattern) throws InvalidDumpOptionException {
+ return null; }
+
+ public static String systemDumpToFile() {
+ return null;
+ }
+ public static String snapDumpToFile(String fileNamePattern) throws InvalidDumpOptionException {
+ return null;
+ }
+ public static String snapDumpToFile() {
+ return null;
+ }
+
+ public static String triggerDump(String dumpOptions) throws InvalidDumpOptionException {
+ return null;
+ }
+
+ public static void setDumpOptions(String dumpOptions) throws InvalidDumpOptionException, DumpConfigurationUnavailableException {
+ }
+
+ public static String[] queryDumpOptions() {
+ return null;
+ }
+
+ public static void resetDumpOptions() throws DumpConfigurationUnavailableException {
+ }
+
+}
diff --git a/test/functional/RasapiTest/dummy_src/com/ibm/jvm/DumpConfigurationUnavailableException.java b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/DumpConfigurationUnavailableException.java
new file mode 100644
index 00000000000..29177a871ec
--- /dev/null
+++ b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/DumpConfigurationUnavailableException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm;
+
+public class DumpConfigurationUnavailableException extends Exception {
+
+ public DumpConfigurationUnavailableException(String message) {
+ }
+
+}
diff --git a/test/functional/RasapiTest/dummy_src/com/ibm/jvm/DumpPermission.java b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/DumpPermission.java
new file mode 100644
index 00000000000..e775209d9e8
--- /dev/null
+++ b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/DumpPermission.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm;
+
+import java.security.BasicPermission;
+
+public class DumpPermission extends BasicPermission {
+
+ public DumpPermission() {
+ super(null);
+ }
+}
diff --git a/test/functional/RasapiTest/dummy_src/com/ibm/jvm/InvalidDumpOptionException.java b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/InvalidDumpOptionException.java
new file mode 100644
index 00000000000..34a02e451f4
--- /dev/null
+++ b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/InvalidDumpOptionException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm;
+
+public class InvalidDumpOptionException extends Exception {
+
+ public InvalidDumpOptionException(String message) {
+ }
+
+}
diff --git a/test/functional/RasapiTest/dummy_src/com/ibm/jvm/Log.java b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/Log.java
new file mode 100644
index 00000000000..fa655121e76
--- /dev/null
+++ b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/Log.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm;
+
+public class Log {
+
+ public static String QueryOptions() {
+ return null;
+ }
+
+ public static int SetOptions(String options) {
+ return 0;
+ }
+
+ private Log() {
+ }
+
+}
diff --git a/test/functional/RasapiTest/dummy_src/com/ibm/jvm/ToolDumpPermission.java b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/ToolDumpPermission.java
new file mode 100644
index 00000000000..ab5f28bf88f
--- /dev/null
+++ b/test/functional/RasapiTest/dummy_src/com/ibm/jvm/ToolDumpPermission.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm;
+
+import java.security.BasicPermission;
+
+public class ToolDumpPermission extends BasicPermission {
+
+ public ToolDumpPermission() {
+ super(null);
+ }
+}
diff --git a/test/functional/RasapiTest/playlist.xml b/test/functional/RasapiTest/playlist.xml
new file mode 100644
index 00000000000..cf9499a3ab5
--- /dev/null
+++ b/test/functional/RasapiTest/playlist.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+ testRASAPI
+
+ backlog issue 426
+ .*mac.*
+
+
+ ant -f $(TEST_RESROOT)$(D)test.xml -Dtest.java.home=$(Q)$(TEST_JDK_HOME)$(D)$(Q) launch_test; \
+ $(TEST_STATUS)
+
+ extended
+
+
+ functional
+
+
+ openj9
+ ibm
+
+
+
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/OutputFile.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/OutputFile.java
new file mode 100644
index 00000000000..1d481a2b83f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/OutputFile.java
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class OutputFile {
+
+ BufferedReader in;
+ String line;
+ String firstReference;
+ String secondReference;
+
+ public OutputFile(String fileName) throws IOException {
+ in = new BufferedReader(new FileReader(fileName));
+ firstReference = null;
+ }
+
+ /**
+ * Yes, finalizers may not have a very good reputation but it can't do any harm
+ */
+ protected void finalize() throws Throwable {
+ try {
+ in.close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+
+ /**
+ * Read through the file looking for the given string. Keep going to the end of the file if necessary.
+ * If the string is found, return true, set the instance variable line, and keep that position in the file.
+ * If the string is not found, return false, leave the file positioned at the end.
+
+ * @param lookFor the string to look for
+ * @return true or false according to whether a line with the string was found
+ * @throws IOException
+ */
+ public boolean skipUnlimitedToLineContaining(String lookFor) throws IOException {
+ line = in.readLine();
+ while (line != null) {
+ if (line.indexOf(lookFor) != -1) {
+ System.err.printf("Successfully found the following line containing \"%s\"\n", lookFor);
+ System.err.printf(line);
+ System.err.printf("\n");
+ return true;
+ }
+ line = in.readLine();
+ }
+ System.err.printf("***Reached end of file before finding a line containing \"%s\"\n", lookFor);
+ return false;
+ }
+
+ /**
+ * Read through the file looking for the given string. Keep going to the end of the file if necessary.
+ * If the string is found AT THE END OF THE LINE, return true, set the instance variable line, and keep that position in the file.
+ * If the string is not found, return false, leave the file positioned at the end.
+ *
+ * This method is especially for searching for the line ending "OBJ com/ibm/dump/tests/types/packed/NestedPacked" in the
+ * classic heapdump. Just using skipUnlimitedToLineContaining finds the lines for NestedPacked1 and NestedPacked2
+
+ * @param lookFor the string to look for
+ * @return true or false according to whether a line with the string was found
+ * @throws IOException
+ */
+ public boolean skipUnlimitedToLineEnding(String lookFor) throws IOException {
+ line = in.readLine();
+ while (line != null) {
+ if (line.endsWith(lookFor)) {
+ System.err.printf("Successfully found the following line ending \"%s\"\n", lookFor);
+ System.err.printf(line);
+ System.err.printf("\n");
+ return true;
+ }
+ line = in.readLine();
+ }
+ System.err.printf("***Reached end of file before finding a line ending \"%s\"\n", lookFor);
+ return false;
+ }
+
+ /**
+ * Read no more than maxLinesToSkip down the file looking for a line containing the given string
+ * Read some number of lines down the file looking for the given string. Read no more than maxLinesToSkip lines.
+ * If the string is found, hold the line in instance variable line and keep the position in the file.
+ * If the string is not found, return false and restore the position in the file to where it was on entry:
+ * by doing so one failing test does not damage the tests that follow.
+ * @param maxLinesToSkip skip no more lines than this
+ * @param lookFor the string to look for
+ * @return true or false according to whether a line with the string was found
+ * @throws IOException
+ */
+ public boolean skipLimitedToLineContaining(int maxLinesToSkip, String lookFor) throws IOException {
+ int linesRead = 0;
+ in.mark(maxLinesToSkip * 200); // generous allocation to allow reset to work. Most lines are < 100 bytes long
+ line = in.readLine();
+ while (line != null && linesRead < maxLinesToSkip) {
+ // System.err.printf("line read was %s\n", line);
+ if (line.indexOf(lookFor) != -1) {
+ System.err.printf("Successfully found a line containing \"%s\"\n", lookFor);
+ return true;
+ }
+ line = in.readLine();
+ linesRead++;
+ }
+ System.err.printf("***Failed to find a line containing \"%s\"\n", lookFor);
+ in.reset();
+ return false;
+ }
+
+
+ /**
+ * Examine the last line read and check that the word at the given position is equal to given string
+ * @param lookFor the string to look for
+ * @param whichWord the index of the word to check
+ * @return
+ */
+ public boolean linePassesCheckForStringAtWord(String lookFor, int whichWord) {
+ if (line == null) {
+ // previous call to skip[Un]limitedToLineContaining has failed
+ // so appropriate error message has been emitted already
+ // just return false and allow test to contine.
+ return false;
+ }
+ return StringUtils.linePassesCheckForStringAtWord(line, whichWord, lookFor);
+ }
+
+ /**
+ * Return true or false depending on whether the word at position whichWord is in the list
+ * of values in validValues
+ *
+ * @param validValues
+ * @param whichWord
+ * @return
+ */
+ public boolean linePassesCheckForStringsAtWord(String[] validValues, int whichWord) {
+ if (line == null) {
+ // previous call to skip[Un]limitedToLineContaining has failed
+ // so appropriate error message has been emitted already
+ // just return false and allow test to contine.
+ return false;
+ }
+ return StringUtils.linePassesCheckForStringsAtWord(line, whichWord, validValues);
+ }
+
+ /**
+ *
+ * @return the first reference that was found by the previous call to skipToNextLineAndCheckReferencesCount.
+ * This is just the first token that was on that line.
+ */
+ public String getFirstReference() {
+ return firstReference;
+ }
+
+ /**
+ *
+ * @return the second reference that was found by the previous call to skipToNextLineAndCheckReferencesCount.
+ * This is just the second token that was on that line.
+ */
+ public String getSecondReference() {
+ return secondReference;
+ }
+
+ /**
+ * Skip down to the lines containing "references:" then check the number of references on the
+ * succeeding line.
+ * @param maxLinesToSkip
+ * @param expectedNumberOfReferences
+ * @return true or false depending on whether the number of references matches the expected number.
+ * @throws IOException
+ */
+ public boolean skipToLineContainingListOfReferencesAndCheckCount(int maxLinesToSkip, int expectedNumberOfReferences) throws IOException {
+
+ if (! skipLimitedToLineContaining(maxLinesToSkip, "references:")) {
+ // if we cannot find the references line, don't go further
+ return false;
+ }
+ return skipToNextLineAndCheckReferencesCount(expectedNumberOfReferences);
+
+ }
+
+ /**
+ * Skip down the output from jdmpview's x/j command looking for the line containing "references:"
+ * @param maxLinesToSkip
+ * @return
+ * @throws IOException
+ */
+ public boolean skipLimitedToReferencesLine(int maxLinesToSkip) throws IOException {
+ if (! skipLimitedToLineContaining(maxLinesToSkip, "references:")) {
+ // if we cannot find the references line, don't go further
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Read the next line, tokenise it, and check that the number of tokens equals the given parameter.
+ * As a side effect, set the instance variable firstReference.
+ *
+ * This method can be called either from the classic heapdump checkers, when the file will be already
+ * positioned on the OBJ line and the references always come on the next line,
+ * or called from skipToLineContainingListOfReferencesAndCheckCount() when checking the
+ * output from jdmpview's x/j command. In either case, the list of references is on the very next line.
+ *
+ *
+ *
+ * @param expectedNumberOfReferences
+ * @return true or false depending on whether the line does or does not contain the given number of tokens.
+ * @throws IOException
+ */
+ public boolean skipToNextLineAndCheckReferencesCount(int expectedNumberOfReferences) throws IOException {
+ // assert
+ // if we are called by one of the classic heapdump checkers we are currently on the OBJ line and
+ // skipping to the next line will put us on the list of references, or
+ // we will have been called from skipToReferencesLineAndCheckCount if we are checking the output
+ // from jdmpview's x/j command during phd checking
+
+
+ String line = in.readLine();
+ if (line == null) {
+ System.err.println("***Unable to check count of references - previous call to find the references lines has failed.");
+ return false;
+ }
+
+ ArrayList references = StringUtils.extractTokensFromLine(line);
+ if (references.size() > 0) {
+ firstReference = references.get(0);
+ } else {
+ firstReference = null;
+ }
+ if (references.size() > 1) {
+ secondReference = references.get(1);
+ } else {
+ secondReference = null;
+ }
+ if (references.size() != expectedNumberOfReferences) {
+ System.err.println("***Failure: there should have been exactly " + expectedNumberOfReferences + " reference(s), not " + references.size());
+ return false;
+ } else {
+ System.err.println("Successfully found exactly " + expectedNumberOfReferences + " reference(s)");
+ return true;
+ }
+ }
+
+ /**
+ * Read the next line, tokenise it, and return the the number of tokens (references).
+ *
+ * This method is called from the classic heapdump checkers, when the file will be already
+ * positioned on the OBJ line and the references always come on the next line
+ *
+ * @return number of references
+ * @throws IOException
+ */
+ public int skipToNextLineAndCountReferences() throws IOException {
+ // if we are called by one of the classic heapdump checkers we are currently on the OBJ line and
+ // skipping to the next line will put us on the list of references
+ String line = in.readLine();
+ if (line == null) {
+ System.err.println("***Unable to check count of references - previous call to find the references lines has failed.");
+ return 0;
+ }
+
+ ArrayList references = StringUtils.extractTokensFromLine(line);
+ return references.size();
+ }
+
+ public static boolean checkReferenceInClassicHeapdumpIsToObject(String fileName, String reference, String className) throws IOException {
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+ System.err.println("Checking that the reference " + reference + " is to an object of type " + className);
+ passed &= o.skipUnlimitedToLineBeginning(reference);
+ passed &= o.linePassesCheckForStringAtWord(className,4);
+ return passed;
+ }
+
+ private boolean skipUnlimitedToLineBeginning(String lookFor) throws IOException {
+ line = in.readLine();
+ while (line != null) {
+ if (line.startsWith(lookFor) ) {
+ System.err.printf("Successfully found a line beginning \"%s\"\n", lookFor);
+ System.err.printf(line);
+ System.err.printf("\n");
+ return true;
+ }
+ line = in.readLine();
+ }
+ System.err.printf("***Reached end of file before finding a line beginning \"%s\"\n", lookFor);
+ return false;
+ }
+
+ public static boolean checkReferenceIsToObject(String fileName, String reference, String className) throws IOException {
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+ System.err.println("Checking that the reference " + reference + " is to an object of type " + className);
+ passed &= o.skipUnlimitedToLineContaining(className + " @ " + reference);
+ return passed;
+ }
+
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/StringUtils.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/StringUtils.java
new file mode 100644
index 00000000000..657027854ee
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/StringUtils.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests;
+
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+
+public class StringUtils {
+
+ /**
+ * Check that the line contains a given value at a given position.
+ * Whether it does or not, write a line to System.err to trace progress.
+ *
+ * @param line the line to check
+ * @param whichWord which word in the line to check
+ * @param requiredValue the number to look for
+ * @return true or false depending on whether the line does indeed contain the given number at the given word
+ */
+ static boolean linePassesCheckForStringAtWord(String line, int whichWord, String requiredValue) {
+ StringTokenizer st = new StringTokenizer(line);
+ String word = "";
+ try {
+ for (int i = 0;i < whichWord; i++) {
+ word = st.nextToken();
+ }
+ } catch (NoSuchElementException e) {
+ System.err.printf("***Failed to find the value %s at word %d in line \"%s\", no such element\n", requiredValue, whichWord, line, word) ;
+ return false;
+ }
+ if (word.equals(requiredValue)) {
+ System.err.printf("Successfully found the value %s at word %d in line \"%s\"\n", requiredValue, whichWord, line) ;
+ return true;
+ } else {
+ System.err.printf("***Failed to find the value %s at word %d in line \"%s\", found %s instead\n", requiredValue, whichWord, line, word) ;
+ return false;
+ }
+
+ }
+
+ /**
+ * Check that the line contains one of a number of given values at a given position.
+ * Whether it does or not, write a line to System.err to trace progress.
+ *
+ * @param line the line to check
+ * @param whichWord which word in the line to check
+ * @param requiredValue the number to look for
+ * @return true or false depending on whether the line does indeed contain the given number at the given word
+ */
+ static boolean linePassesCheckForStringsAtWord(String line, int whichWord, String[] requiredValues) {
+ StringTokenizer st = new StringTokenizer(line);
+ String word = "";
+ try {
+ for (int i = 0;i < whichWord; i++) {
+ word = st.nextToken();
+ }
+ } catch (NoSuchElementException e) {
+ System.err.printf("***Failed to find any value at word %d in line \"%s\", no such element\n", whichWord, line, word) ;
+ return false;
+ }
+ for (String requiredValue : requiredValues) {
+ if (word.equals(requiredValue)) {
+ System.err.printf("Successfully found the value %s at word %d in line \"%s\"\n", requiredValue, whichWord, line) ;
+ return true;
+ }
+ }
+ System.err.printf("***Failed to find any of the required values at word %d in line \"%s\", found %s instead. ", whichWord, line, word) ;
+ System.err.printf("The required values were:") ;
+ for (String requiredValue : requiredValues) {
+ System.err.printf(requiredValue + " ");
+ }
+ System.err.printf("\n");
+ return false;
+ }
+
+
+ /**
+ * Given a line break it into an array of tokens (words)
+ * @param line
+ * @return arraylist of tokens (words)
+ */
+ public static ArrayList extractTokensFromLine(String line) {
+ ArrayList tokens = new ArrayList();
+ StringTokenizer st = new StringTokenizer(line);
+ while (st.hasMoreTokens()) {
+ String word = st.nextToken();
+ tokens.add(word);
+ }
+ return tokens;
+ }
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/CheckClassicHeapdump.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/CheckClassicHeapdump.java
new file mode 100644
index 00000000000..5f764bf92cc
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/CheckClassicHeapdump.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * This class checks a classic heapdump containing packed objects
+ *
+ * @author matthew
+ *
+ */
+public class CheckClassicHeapdump {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.err.println("A file containing a classic heapdump is required to check.");
+ System.exit(1);
+ }
+
+ String fileName = args[0];
+ boolean passed = true;
+
+ System.err.println("Classic Heapdump Checker");
+ System.err.println("Checking " + fileName);
+
+ try{
+ /**
+ * Test 1. Check PackedPrimitives
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 1. Check PackedPrimitives");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest1PackedPrimitivesChecker.check(fileName);
+
+ /**
+ * Test 2. Check array of PackedPrimitives
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 2. Check array of PackedPrimitives");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest2ArrayOfPackedPrimitivesChecker.check(fileName);
+
+ /**
+ * Test 3. Check PackedMixed
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 3. Check PackedMixed");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest3PackedMixedOneRefChecker.check(fileName);
+
+ /**
+ * Test 4. Check array of PackedMixed
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 4. Check array of PackedMixed");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest4ArrayOfPackedMixedOneRefChecker.check(fileName);
+
+ /**
+ * Test 5. Check array of PackedMixedTwoRefs
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 5. Check PackedMixedTwoRefs");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.check(fileName);
+
+ /**
+ * Test 6. Check PackedMixedWithReferenceToSelf
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 6. Check PackedMixedWithReferenceToSelf");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest6PackedMixedWithReferenceToSelfChecker.check(fileName);
+
+ /**
+ * Test 7. Check NestedPacked
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 7. Check NestedPacked");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest7NestedPackedChecker.check(fileName);
+
+ /**
+ * Test 8. Check PackedIntsArray
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 8. Check PackedIntsArray");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest8PackedIntsArrayChecker.check(fileName);
+
+ /**
+ * Test 9. Check array of PackedMixedWithReferenceToSelf and the derived object
+ */
+ System.err.println("\n**************************************************");
+ System.err.println("* 9. Check PackedMixedArrayElement");
+ System.err.println("**************************************************");
+ passed &= ClassicHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.check(fileName);
+
+ } catch (FileNotFoundException e) {
+ System.err.println("FileNotFoundException occured reading " + fileName);
+ e.printStackTrace(System.err);
+ System.exit(1);
+ } catch (IOException e) {
+ System.err.println("IOException occured reading " + fileName);
+ e.printStackTrace(System.err);
+ System.exit(1);
+ }
+
+ if( passed ) {
+ System.err.println("\n**************************************************");
+ System.err.println("CheckClassicHeapdump: All tests passed.");
+ System.exit(0);
+ } else {
+ System.err.println("\n**************************************************");
+ System.err.println("CheckClassicHeapdump: Some or all tests failed, see messages in tests 1 to 9 above.");
+ System.exit(1);
+ }
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest1PackedPrimitivesChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest1PackedPrimitivesChecker.java
new file mode 100644
index 00000000000..4196c8f4479
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest1PackedPrimitivesChecker.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest1PackedPrimitivesChecker {
+
+ /**
+ * Check through the classic heapdump looking for the lines containing "OBJ com/ibm/dump/tests/types/packed/PackedPrimitives".
+ *
+ * Check there are no references from the objects - this will check that the curious and irritating self-reference
+ * that gc returns for on-heap packed objects has been suppressed correctly when the dump was written.
+ *
+ * The expected output is lines such as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+ String[] validSizes = {
+ "[48]", // on heap 32 and 64cr
+ "[16]", // off heap 32 and 64cr
+ "[56]", // on heap 64
+ "[24]"}; // off heap 64
+
+ String objectLine = "OBJ com/ibm/dump/tests/types/packed/PackedPrimitives";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+
+ // check for three OBJ lines, one of which will have a single reference, the others no references
+ boolean passed = true;
+ int refCount = 0;
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= (refCount == 1); // expect one reference found in the three objects
+
+ if (!passed) {
+ System.err.println("ClassicHeapdumpTest1PackedPrimitivesChecker failed");
+ }
+ return passed;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest2ArrayOfPackedPrimitivesChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest2ArrayOfPackedPrimitivesChecker.java
new file mode 100644
index 00000000000..b025ae65fbc
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest2ArrayOfPackedPrimitivesChecker.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest2ArrayOfPackedPrimitivesChecker {
+
+ /**
+ * Check through the classic heapdump looking for two arrays of PackedPrimitives and check the length.
+ * Check there are no references from the arrays - this will check that the odd self-reference
+ * that on-heap packed objects have has been suppressed correctly.
+ *
+ * The expected output is similar to:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+
+ String[] validSizes = {
+ "[336]", // on heap 32
+ "[16]", // off heap 32
+ "[344]", // on heap 64cr
+ "[24]", // off heap 64cr
+ "[352]", // on heap 64
+ "[32]"}; // off heap 64
+
+ String objectLine = "OBJ com/ibm/dump/tests/types/packed/PackedPrimitives$Array";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+ int refCount = 0;
+ passed &= o.skipUnlimitedToLineContaining(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= o.skipUnlimitedToLineContaining(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= (refCount == 1); // expect one reference found in the two objects
+
+ if (!passed) {
+ System.err.println("ClassicHeapdumpTest2ArrayOfPackedPrimitivesChecker failed");
+ }
+ return passed;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest3PackedMixedOneRefChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest3PackedMixedOneRefChecker.java
new file mode 100644
index 00000000000..a16dce1ce40
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest3PackedMixedOneRefChecker.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest3PackedMixedOneRefChecker {
+
+ /**
+ * Check through the classic heapdump looking for the PackedMixed object, and the one reference
+ * to the NotPackedPrimitives contained therein.
+ *
+ * Rely on the NotPackedPrimitives immediately after in the file, which is a weakness, but seems to
+ * always work.
+ *
+ * The expected output is lines such as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+ String[] validSizes = {
+ "[24]", // on heap 32 and 64cr
+ "[40]"}; // on heap 64
+
+ String objectLine = "OBJ com/ibm/dump/tests/types/packed/PackedMixedOneRef";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(2);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+
+ return passed;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest4ArrayOfPackedMixedOneRefChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest4ArrayOfPackedMixedOneRefChecker.java
new file mode 100644
index 00000000000..71ece44fab5
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest4ArrayOfPackedMixedOneRefChecker.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest4ArrayOfPackedMixedOneRefChecker {
+
+ /**
+ * Check through the classic heapdump looking for the array of PackedMixed and check the length.
+ * Each PackedMixed object contains a reference to a non-packed object within it.
+ * When we iterate the references in the array we expect to see 10 references. These are in fact references
+ * to the non-packed objects that each PackedMixed contains, not to the PackedMixed objects themselves as
+ * would be the case for an array of non-packed objects.
+ *
+ * The expected output is similar to:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+
+ String[] validSizes = {
+ "[96]", // on heap 32
+ "[104]", // on heap 64cr
+ "[192]"}; // on heap 64
+
+ String objectLine = " OBJ com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineContaining(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(11);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+
+ return passed;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.java
new file mode 100644
index 00000000000..e830953e2fb
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker {
+
+
+
+ /**
+ * Check through the classic heapdump looking for the array of PackedMixedTwoRefs and
+ * check the length. Also check the references.
+ *
+ * The essential point is that in the array we will see the references, not to the PackedMixedTwoRefs objects
+ * as we would if this were a normal array, but the references to the objects to which the PackedMixed objects point.
+ * Hence we expect to see 20 references, not 10.
+ *
+ * The expected output is similar to:
+ *
+ 0x2EF48938 [136] OBJ [Lcom/ibm/dump/tests/types/packed/PackedMixedTwoRefs;
+ 0x2EF48938 0x2EF48D20 [ ... 18 references removed for brevity ... ] 0x2EF489F0 <-------------------- one self-ref then 20 references to NotPackedPrimitives objects
+ 0x2EF489C0 [48] OBJ com/ibm/dump/tests/types/notpacked/NotPackedPrimitives
+ [blank line]
+
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+
+ String[] validSizes = {
+ "[136]", // on heap 32
+ "[144]", // on heap 64cr
+ "[272]"}; // on heap 64
+
+ String objectLine = " OBJ com/ibm/dump/tests/types/packed/PackedMixedTwoRefs$Array";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineContaining(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(21);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+
+ return passed;
+
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest6PackedMixedWithReferenceToSelfChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest6PackedMixedWithReferenceToSelfChecker.java
new file mode 100644
index 00000000000..2ba459e95ab
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest6PackedMixedWithReferenceToSelfChecker.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest6PackedMixedWithReferenceToSelfChecker {
+
+ /**
+ * Check through the classic heapdump looking for the PackedMixedWithReferenceToSelf object, and check that it has two
+ * references to itself.
+ *
+ * The expected output is lines such as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+
+
+ String[] validSizes = {
+ "[24]", // on heap 32 and 64cr
+ "[40]"}; // on heap 64
+
+ String objectLine = " OBJ com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineContaining(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+
+ passed &= o.skipToNextLineAndCheckReferencesCount(2);
+
+ String firstReference = o.getFirstReference();
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, firstReference, "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf");
+
+ String secondReference = o.getSecondReference();
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf");
+
+
+ return passed;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest7NestedPackedChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest7NestedPackedChecker.java
new file mode 100644
index 00000000000..527a7e32061
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest7NestedPackedChecker.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest7NestedPackedChecker {
+
+ /**
+ * Check through the classic heapdump looking for the NestedPacked object.
+ *
+ * The expected output is as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+ String[] validSizes = {
+ "[24]", // on heap 32
+ "[16]", // off heap 32
+ "[32]", // on heap 64cr
+ "[16]", // off heap 64cr
+ "[40]", // on heap 64
+ "[24]"}; // off heap 64
+
+ String objectLine = " OBJ com/ibm/dump/tests/types/packed/NestedPacked";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ // the two instances can appear in either order, so cannot check number of refs
+// passed &= o.skipToNextLineAndCheckReferencesCount(1);
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+// passed &= o.skipToNextLineAndCheckReferencesCount(0);
+
+ return passed;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest8PackedIntsArrayChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest8PackedIntsArrayChecker.java
new file mode 100644
index 00000000000..08c05b0f0cd
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest8PackedIntsArrayChecker.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest8PackedIntsArrayChecker {
+
+ /**
+ * Check through the classic heapdump looking for the on and off heap PackedIntsArray objects.
+ *
+ * The expected output is as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+
+ String[] validSizes = {
+ "[40]", // on heap 32
+ "[16]", // off heap 32
+ "[48]", // on heap 64cr
+ "[16]", // off heap 64cr
+ "[56]", // on heap 64
+ "[24]", // off heap 64
+ };
+
+ String objectLine = " OBJ com/ibm/dump/tests/types/packed/PackedIntsArray";
+ System.err.println("\nChecking the output for \"" + objectLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(1);
+
+ passed &= o.skipUnlimitedToLineEnding(objectLine);
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(0);
+
+ return passed;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.java
new file mode 100644
index 00000000000..479c3b5cbc3
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/classic_heapdump_packed_objects/ClassicHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.classic_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class ClassicHeapdumpTest9ArrayOfPackedMixedArrayElementChecker {
+
+ /**
+ * Check through the classic heapdump looking for the derived object representing the
+ * element in the array of PackedMixedWithReferenceToSelf and
+ * check that it points back to the array.
+ *
+ * The expected output is as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean check(String fileName) throws IOException {
+ String[] validArraySizes = {
+ "[24]", // on heap 32
+ "[32]", // on heap 64cr
+ "[48]"}; // on heap 64
+
+ String arrayLine = " OBJ com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array";
+ System.err.println("\nChecking the output for \"" + arrayLine + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ boolean passed = true;
+
+ passed &= o.skipUnlimitedToLineContaining(arrayLine);
+ passed &= o.linePassesCheckForStringsAtWord(validArraySizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(2);
+ String secondReference = o.getSecondReference();
+
+ // check the array points to the element
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedArrayElement");
+
+
+ String[] validElementSizes = {"[16]","[24]"}; // on-heap 32 and 64cr, on-heap 64
+
+ String className = "com/ibm/dump/tests/types/packed/PackedMixedArrayElement";
+ System.err.println("\nLooking for object at " + secondReference + " and checking that it is a PackedMixedArrayElement");
+
+ passed &= o.skipUnlimitedToLineContaining(secondReference);
+ passed &= o.linePassesCheckForStringAtWord(className,4);
+ passed &= o.linePassesCheckForStringsAtWord(validElementSizes,2);
+ passed &= o.skipToNextLineAndCheckReferencesCount(1);
+ secondReference = o.getFirstReference();
+
+ // check the element points to the array
+ passed &= OutputFile.checkReferenceInClassicHeapdumpIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array");
+
+ return passed;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CheckCommandOutput.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CheckCommandOutput.java
new file mode 100644
index 00000000000..eeebb838381
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CheckCommandOutput.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.commands;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This is the main class to validate the command output from Jdmpview.
+ * Usage:
+ * java com.ibm.dump.tests.commands.CheckCommandOutput
+ *
+ * The is what we defined as the -outfile option when launching jdmpview. It is the result
+ * of executing commands in a command input file (defined as the -cmdfile option when launching Jdmpview).
+ *
+ * The defines what to check in the .
+ * Note:
+ * (1) The contains a list of command checking units.
+ * Each command checking unit contains 1 or more lines, the first line has to be the command line, followed
+ * by the checker lines. A command line always starts with "command :"; a checker line always starts "checker :".
+ * (2) The command checking unit has to be composed in the exact order as the commands in the command input file.
+ * (3) You can use "#" or "//" to start a comment line. Command line will be ignored by the file parser.
+ * (4) Empty lines (lines with only spaces) will be ignored by the file parser.
+ *
+ * Each checker line has to start with the full class name (including the package name). It can follow by its arguments (if any).
+ * The arguments details are defined by each checker itself.
+ *
+ * @author Manqing Li
+ *
+ */
+public class CheckCommandOutput {
+ private static final String PROMPT_FORMAT_DEFAULT = "> ";
+
+ public static void main(String[] args) {
+
+ if (args.length < 2) {
+ System.err.println("The command output file and the command checking file are required to check.");
+ System.exit(1);
+ }
+
+ CheckCommandOutput checker = new CheckCommandOutput();
+ List commandOutputs = null;
+ try {
+ commandOutputs = checker.readFile(args[0]);
+ } catch (FileNotFoundException e) {
+ System.err.println("Command output file " + args[0] + " not found.");
+ System.exit(1);
+ } catch (IOException e) {
+ System.err.println("Failed to read command output file " + args[0]);
+ System.exit(1);
+ }
+
+ List commandChecker = null;
+
+ try {
+ commandChecker = checker.readFile(args[1]);
+ } catch (FileNotFoundException e) {
+ System.err.println("Command checking file " + args[1] + " not found.");
+ System.exit(1);
+ } catch (IOException e) {
+ System.err.println("Failed to read command checking file " + args[1]);
+ System.exit(1);
+ }
+
+ boolean passed = checker.check(commandOutputs, commandChecker);
+ if(passed) {
+ System.err.println("Tests passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Tests failed.");
+ System.exit(1);
+ }
+ }
+
+ private boolean check(List commandOutputs, List commandCheckerLines) {
+ boolean allTestsSucceeded = true;
+ List commandCheckingUnits = parseCheckers(commandCheckerLines);
+ if(commandCheckerLines == null || commandCheckerLines.size() == 0) {
+ System.err.println("Warning : no checkers are found.\n");
+ return true;
+ }
+ OutputContentParser parser = new OutputContentParser(commandOutputs, PROMPT_FORMAT_DEFAULT + commandCheckingUnits.get(0).targetCommand);
+ for(int i = 0; i < commandCheckingUnits.size(); i++) {
+ CommandWithCheckers aCheckingUnit = commandCheckingUnits.get(i);
+ String nextCommand = null;
+ if( i < commandCheckingUnits.size() - 1) {
+ nextCommand = commandCheckingUnits.get(i + 1).targetCommand;
+ }
+ List output = parser.extractOutputLinesUntilTheStartOfNextCommand(aCheckingUnit.targetCommand, nextCommand);
+
+ if(aCheckingUnit.hasCheckers()) {
+ System.err.println("Checking the output from command : " + aCheckingUnit.targetCommand);
+ if(aCheckingUnit.checking(output) == false) {
+ System.err.println("Tests failed.");
+ allTestsSucceeded = false;
+ } else {
+ System.err.println("Tests passed.");
+ }
+ }
+ }
+ return allTestsSucceeded;
+ }
+
+ private static final Pattern CHECKER_LINE = Pattern.compile("\\s*//\\s*checker\\s*:\\s*(\\S+.*)", Pattern.CASE_INSENSITIVE + Pattern.DOTALL);
+ private List parseCheckers(List allLines) {
+ List result = new ArrayList();
+ String tmpCommand = null;
+ List tmpCheckerLineList = new ArrayList();
+ for(String line : allLines) {
+ if(line.trim().length() == 0) {
+ continue;
+ }
+ if(isCommentsLine(line)) {
+ Matcher matcher = CHECKER_LINE.matcher(line);
+ if(matcher.matches()) {
+ tmpCheckerLineList.add(matcher.group(1));
+ }
+ } else {
+ if(tmpCommand != null) {
+ result.add(new CommandWithCheckers(tmpCommand, tmpCheckerLineList));
+ }
+ tmpCommand = line;
+ tmpCheckerLineList = new ArrayList();
+ }
+ }
+ if(tmpCommand != null) {
+ result.add(new CommandWithCheckers(tmpCommand, tmpCheckerLineList));
+ }
+
+ return result;
+ }
+
+ private List readFile(String filePath) throws FileNotFoundException, IOException {
+ BufferedReader in = new BufferedReader(new FileReader(filePath));
+ List result = new ArrayList();
+ String line = null;
+ while((line = in.readLine()) != null) {
+ result.add(line);
+ }
+ in.close();
+ return result;
+ }
+
+ private boolean isCommentsLine(String line) {
+ return line.trim().startsWith("#") || line.trim().startsWith("//");
+ }
+
+ private class CommandWithCheckers {
+ public CommandWithCheckers(String targetCommand, List checkers) {
+ this.targetCommand = targetCommand;
+ this.checkingLines = (checkers == null ? new ArrayList() : checkers);
+ }
+ public boolean checking(List output) {
+ for(String line : checkingLines) {
+ line = line.trim();
+ int index = StringUtils.getFirstTokenEndIndex(line);
+ String checkerClass = line.substring(0, index + 1);
+ try {
+ ICommandOutputChecker checkerObject = (ICommandOutputChecker)Class.forName(checkerClass).newInstance();
+
+ if(checkerObject.check(targetCommand, line.substring(index + 1).trim(), output) == false) {
+ System.err.println("The outputs are : ");
+ for(String outputLine : output) {
+ System.err.println("\t" + outputLine);
+ }
+ System.err.println("The checker is : ");
+ System.err.println("\t" + line);
+ return false;
+ }
+ } catch (IllegalAccessException e) {
+ e.printStackTrace(System.err);
+ System.err.println("Failed to create the checker " + checkerClass);
+ return false;
+ } catch (InstantiationException e) {
+ e.printStackTrace(System.err);
+ System.err.println("Failed to create the checker " + checkerClass);
+ return false;
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace(System.err);
+ System.err.println("Failed to create the checker " + checkerClass);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean hasCheckers() {
+ return this.checkingLines.size() > 0;
+ }
+
+ private String targetCommand;
+ private List checkingLines;
+ }
+
+ private class OutputContentParser {
+ public OutputContentParser(List output, String startOfFirstCommand) {
+ this.output = output;
+ this.position = 0;
+ while(this.position < output.size() && startOfFirstCommand.trim().equals(output.get(position).trim()) == false) {
+ this.position++;
+ }
+ }
+
+ public List extractOutputLinesUntilTheStartOfNextCommand(String command, String nextCommand) {
+ List result = new ArrayList();
+
+ if(position < output.size()) {
+ if(output.get(position).trim().equalsIgnoreCase(PROMPT_FORMAT_DEFAULT + command) == false) {
+ System.err.println("Failed to found the matching output for command " + command);
+ System.err.println("Tests failed.");
+ System.exit(1);
+ }
+ }
+ position++;
+ String commandInputLine = nextCommand == null ? null : PROMPT_FORMAT_DEFAULT + nextCommand;
+ while(position < output.size()) {
+ String line = output.get(position);
+ if(commandInputLine == null) {
+ // if the startOfNextCommand is null, then position == output.size() to exit the while loop.
+ result.add(line);
+ } else {
+ // if the startOfNextCommand is NOT null, then the position will point to the
+ //nextCommand to exit the while loop or it points to the end of the list.
+ if(commandInputLine.trim().equals(line.trim())) {
+ break;
+ } else {
+ result.add(line);
+ }
+ }
+ position++;
+ }
+ return result;
+ }
+
+ private int position;
+ private List output;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/ContainingString.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/ContainingString.java
new file mode 100644
index 00000000000..6ee6461ebd5
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/ContainingString.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.commands;
+
+import java.util.List;
+/**
+ * This class is to check if the given string is contained in any of the output lines.
+ * Usage:
+ * com.ibm.dump.tests.commands.ContainingString [N] [-i] [-negate]
+ * Use N to check the Nth line only (N starts from 0!).
+ * Note, Use -1 to check the last line, and -N to check the Nth line from the last line.
+ * Use -i to ignore case.
+ * Use -negate to fail the test when the given string is contained in any of the output lines.
+ *
+ * @author Manqing Li
+ *
+ */
+public class ContainingString implements ICommandOutputChecker {
+
+ public boolean check(String command, String args, List outputLines) {
+ boolean ignoreCase = false;
+ boolean negate = false;
+ int n = Integer.MAX_VALUE;
+
+ args = args.trim();
+ int tokenEndIndex = StringUtils.getFirstTokenEndIndex(args);
+
+ while((tokenEndIndex = StringUtils.getFirstTokenEndIndex(args)) >= 0) {
+ String token = args.substring(0, tokenEndIndex + 1).trim();
+ if(token.equals(ARG_IGNORE_CASE)) {
+ ignoreCase = true;
+ args = args.substring(tokenEndIndex + 1).trim();
+ } else if (token.equals(ARG_NEGATE)) {
+ negate = true;
+ args = args.substring(tokenEndIndex + 1).trim();
+ } else if(n == Integer.MAX_VALUE) {
+ try {
+ n = Integer.parseInt(token);
+ args = args.substring(tokenEndIndex + 1).trim();
+ } catch (NumberFormatException e) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if(n != Integer.MAX_VALUE) {
+ if(n < 0) {
+ n = outputLines.size() + n;
+ }
+ if(n >= 0 && n < outputLines.size()) {
+ return StringUtils.contain(outputLines.get(n), args, ignoreCase) != negate;
+ }
+ return negate == false;
+ }
+
+ if(StringUtils.containInAnyLines(outputLines, args, ignoreCase)) {
+ return negate == false;
+ } else {
+ return negate == true;
+ }
+ }
+
+ private static final String ARG_IGNORE_CASE = "-i";
+ private static final String ARG_NEGATE = "-negate";
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CountingChars.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CountingChars.java
new file mode 100644
index 00000000000..a7347e68c08
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CountingChars.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.commands;
+
+import java.util.List;
+import java.util.StringTokenizer;
+/**
+ * This class is to count how many characters in the output lines.
+ * Note, the leading spaces and tailing spaces will be trimmed for all lines
+ * before it starts counting.
+ * Usage:
+ * com.ibm.dump.tests.commands.CountingChars [] [max=] [min=]
+ *
+ * @author Manqing Li
+ *
+ */
+public class CountingChars implements ICommandOutputChecker {
+
+ public boolean check(String command, String args, List output) {
+ int counter = count(output);
+ StringTokenizer st = new StringTokenizer(args);
+ while(st.hasMoreTokens()) {
+ String t = st.nextToken();
+ int index = t.indexOf("=");
+ if(index > 0) {
+ String key = t.substring(0, index);
+ String value = t.substring(index + 1);
+
+ if(MAX.equals(key)) {
+ if(counter > Integer.parseInt(value)) {
+ return false;
+ }
+ } else if(MIN.equals(key)) {
+ if(counter < Integer.parseInt(value)) {
+ return false;
+ }
+ }
+ } else if( counter != Integer.parseInt(t)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private int count (List output) {
+ int counter = 0;
+ for(String line : output) {
+ counter += line.trim().length();
+ }
+ return counter;
+ }
+
+ private static final String MAX = "max";
+ private static final String MIN = "min";
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CountingLines.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CountingLines.java
new file mode 100644
index 00000000000..9a393525a48
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/CountingLines.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.commands;
+
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * This class is to count how many lines a command outputs.
+ * Usage:
+ * com.ibm.dump.tests.commands.CountingLines [] [max=] [min=]
+ *
+ * @author Manqing Li
+ *
+ */
+public class CountingLines implements ICommandOutputChecker {
+
+ public boolean check(String command, String args, List output) {
+ int counter = count(output);
+ StringTokenizer st = new StringTokenizer(args);
+ while(st.hasMoreTokens()) {
+ String t = st.nextToken();
+ int index = t.indexOf("=");
+ if(index > 0) {
+ String key = t.substring(0, index);
+ String value = t.substring(index + 1);
+
+ if(MAX.equals(key)) {
+ if(counter > Integer.parseInt(value)) {
+ return false;
+ }
+ } else if(MIN.equals(key)) {
+ if(counter < Integer.parseInt(value)) {
+ return false;
+ }
+ }
+ } else if( counter != Integer.parseInt(t)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private int count (List output) {
+ return output.size();
+ }
+
+ private static final String MAX = "max";
+ private static final String MIN = "min";
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/ICommandOutputChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/ICommandOutputChecker.java
new file mode 100644
index 00000000000..a126d260f38
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/ICommandOutputChecker.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.commands;
+
+import java.util.List;
+
+/**
+ * This is the interface all CommandOutputChecker has to implement.
+ * Note, if any constructors are implemented at all, the implementation class has to
+ * provide the default constructor (the one with no argument).
+ *
+ * @author Manqing Li
+ *
+ */
+public interface ICommandOutputChecker {
+
+ /**
+ * To check the output.
+ *
+ * @param command The command string for this checker. Normally this is the class name (with package).
+ * @param args The arguments to this checker.
+ * @param outputLines The output lines to be checked.
+ *
+ * @return true if the checking was successful; false otherwise.
+ */
+ public boolean check(String command, String args, List outputLines);
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/StringUtils.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/StringUtils.java
new file mode 100644
index 00000000000..c856cc0abb7
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/commands/StringUtils.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.commands;
+
+import java.util.List;
+
+public class StringUtils {
+
+ /**
+ * To get the first token end index. Note tokens are separated by spaces.
+ *
+ * @param line The string containing all tokens.
+ *
+ * @return The end index of the first token.
+ */
+ public static int getFirstTokenEndIndex(String line) {
+ return getNextTokenEndIndex(0, line);
+ }
+ /**
+ * To get the next token end index. Note tokens are separated by spaces.
+ *
+ * @param startIndex The start index from where the first token is to be searched.
+ * @param line The string containing all tokens.
+ *
+ * @return The end index of the next token.
+ */
+ public static int getNextTokenEndIndex(int startIndex, String line) {
+ int index = startIndex;
+
+ // move over to the first no space char.
+ for(; index < line.length(); index++) {
+ if(" \t\n\r\f".indexOf(line.charAt(index)) < 0) {
+ break;
+ }
+ }
+
+ // find the first non-space char or the end of the line.
+ while(index < line.length()) {
+ if(" \t\n\r\f".indexOf(line.charAt(index)) >= 0) {
+ return index - 1;
+ }
+ if(index == line.length() - 1) {
+ return index;
+ } else {
+ index++;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * To check if any line in the list contains a special string.
+ *
+ * @param allLines All the lines.
+ * @param strToSearch The string to look for.
+ * @param ignoreCase Indicating whether the comparison should ignore case.
+ *
+ * @return true if any of the line contains the string to be searched;
+ * false otherwise.
+ */
+ public static boolean containInAnyLines(List allLines, String strToSearch, boolean ignoreCase) {
+
+ for(String line : allLines) {
+ if(ignoreCase) {
+ if(line.toLowerCase().contains(strToSearch.toLowerCase())) {
+ return true;
+ }
+ } else {
+ if(line.contains(strToSearch)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * To check if any line in the list contains a special string.
+ *
+ * @param str The string to be searched on.
+ * @param strToSearch The string to look for.
+ * @param ignoreCase Indicating whether the comparison should ignore case.
+ *
+ * @return true if string contains the string to be searched;
+ * false otherwise.
+ */
+ public static boolean contain(String str, String strToSearch, boolean ignoreCase) {
+
+ if(ignoreCase) {
+ if(str.toLowerCase().contains(strToSearch.toLowerCase())) {
+ return true;
+ }
+ } else {
+ if(str.contains(strToSearch)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/excessive_gc/HeapAllocation.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/excessive_gc/HeapAllocation.java
new file mode 100644
index 00000000000..ce3ecfbec0f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/excessive_gc/HeapAllocation.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.excessive_gc;
+
+import sun.misc.*;
+import java.util.*;
+
+public class HeapAllocation {
+
+ static Hashtable globalTable = new Hashtable();
+
+ public static void main(String args[]) {
+ // Takes 2 parameters - integer numbers of threads and objects
+ int nThreads=1,nObjects=100000;
+
+ if (args != null && args.length == 2) {
+ try {
+ nThreads = Integer.parseInt(args[0]);
+ nObjects = Integer.parseInt(args[1]);
+ } catch (NumberFormatException nfe){
+ System.out.println("Test program HeapAllocation.main() - bad parameter(s)");
+ return;
+ }
+ }
+
+ Object[] objects = new Object[nThreads];
+ for (int i=0; i threadNums = new ArrayList();
+ List threadNames = new ArrayList();
+ while(true) {
+ if( line.startsWith("2LKDEADLOCKTHR") ) {
+ String threadName = getQuotedThreadName(line);
+ int threadNo = getThreadNumber(threadName);
+ threadNames.add(threadName);
+ threadNums.add(threadNo);
+ }
+ if( line.startsWith("NULL")) {
+ break; // Check we have a valid cycle outside this loop.
+ }
+ line = in.readLine();
+ }
+ // The threads should all be in a cycle waiting on each other in order.
+ // Validate they are all the same kind of thread and the numbers are in order.
+ int currentThread = threadNums.get(0);
+ int firstThread = currentThread;
+ String currentName = threadNames.get(0);
+ String firstName = currentName;
+ String threadPrefix = currentName.substring( 0, currentName.indexOf("##")).trim();
+ // Length of the deadlock chain is (threadNums.size() - 1) since the first thread repeats to complete the chain.
+ System.err.println("Checking deadlock chain for \"" + threadPrefix + "\" threads that is " + (threadNums.size() - 1) + " threads long");
+ for( int i = 1; i < threadNums.size(); i++ ) {
+ int nextThread = threadNums.get(i);
+ String nextThreadName = threadNames.get(i);
+ if( nextThread != currentThread + 1 && nextThread != 0 ) {
+ System.err.println("Threads out of order: " + threadNames.get(i) + " after " + currentThread );
+ passed &= false;
+ break;
+ }
+ if( !nextThreadName.startsWith(threadPrefix)) {
+ System.err.println("Wrong thread type: " + threadNames.get(i) + " does not start with " + currentThread );
+ passed &= false;
+ break;
+ }
+ currentThread = nextThread;
+ currentName = nextThreadName;
+ }
+ if( firstThread == currentThread ) {
+ System.err.println("Complete thread cycle found, confirmed deadlock for " + threadPrefix + " threads" );
+ }
+ System.err.println("------------");
+
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ System.exit(1);
+ }
+ if( deadlockCount == expectedDeadlocks ) {
+ passed &= true;
+ }
+
+ return passed;
+ }
+
+ /**
+ * Given a string, returns the contents of the first quoted string.
+ * (Which in java cores is generally the thread name.
+ * @param line
+ * @return
+ */
+ public static String getQuotedThreadName(String line) {
+ // Pull the thread name out of a line that looks like:
+ // 3XMTHREADINFO "main" J9VMThread:0x00129100, j9thread_t:0x002B5A30, java/lang/Thread:0x00DDC4F8, state:R, prio=5
+ // There are threads that don't have quotes, but they aren't Java threads so we aren't
+ // interested here.
+ int openQuote = -1;
+ int closeQuote = -1;
+ openQuote = line.indexOf('"');
+ closeQuote = line.indexOf('"', openQuote + 1);
+ if( openQuote > -1 && closeQuote > -1 ) {
+ String threadName = line.substring(openQuote + 1, closeQuote);
+ return threadName;
+ } else {
+ return null;
+ }
+ }
+
+ public static int getThreadNumber(String threadName) {
+ // Pull the thread number out of a name that looks like:
+ // Deadlock Thread ##6##
+ int openQuote = -1;
+ int closeQuote = -1;
+ openQuote = threadName.indexOf("##");
+ closeQuote = threadName.indexOf("##", openQuote + 1);
+ if( openQuote > -1 && closeQuote > -1 ) {
+ String threadNo_string = threadName.substring(openQuote + 2, closeQuote);
+ int threadNo = Integer.parseInt(threadNo_string);
+ return threadNo;
+ } else {
+ return Integer.MIN_VALUE;
+ }
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/CheckJdmpviewDeadlock.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/CheckJdmpviewDeadlock.java
new file mode 100644
index 00000000000..cda59c64288
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/CheckJdmpviewDeadlock.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_deadlock;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class check a javacore for a few pre-setup deadlock cycles.
+ *
+ * @author hhellyer
+ *
+ */
+public class CheckJdmpviewDeadlock {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.err.println("An input file is required to check.");
+ System.exit(1);
+ }
+ String fileName = args[0];
+
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(fileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + fileName + " not found.");
+ System.exit(1);
+ }
+ if (in == null) {
+ System.err.println("Failed to open file: " + fileName);
+ System.exit(1);
+ }
+
+ boolean passed = true;
+
+ passed &= checkDeadlockSection(in);
+
+ if( passed ) {
+ System.err.println("Test passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Test failed.");
+ System.exit(1);
+ }
+ }
+
+ private static boolean checkDeadlockSection(BufferedReader in) {
+ String line;
+ boolean passed = true;
+ int deadlockCount = 0;
+ final int expectedDeadlocks = 3;
+
+ // Fast forward to "deadlock loop:"
+ // (Fail if we don't find it.)
+ try {
+ line = readLine(in);
+ while( line != null ) {
+ while (line != null && !line.startsWith("deadlock loop:") && deadlockCount < expectedDeadlocks) {
+ line = readLine(in);
+ }
+ if( line == null ) {
+ System.err.println("Null line");
+ passed = false;
+ break;
+ }
+ if( deadlockCount == expectedDeadlocks ) {
+ break;
+ }
+ deadlockCount++;
+ System.err.println("Found a deadlock, line: " + line);
+ line = readLine(in);
+ // Now validate the deadlock is reported correctly.
+ List threadNums = new ArrayList();
+ List threadNames = new ArrayList();
+ while(true) {
+ if( line.startsWith("thread: ") ) {
+ String threadName = line.substring(line.indexOf("thread: ") + "thread: ".length(), line.indexOf("id: "));
+ int threadNo = getThreadNumber(threadName);
+ threadNames.add(threadName);
+ threadNums.add(threadNo);
+ } else {
+ break; // Check we have a valid cycle outside this loop.
+ }
+ line = readLine(in);
+ }
+ // The threads should all be in a cycle waiting on each other in order.
+ // Validate they are all the same kind of thread and the numbers are in order.
+ int currentThread = threadNums.get(0);
+ int firstThread = currentThread;
+ String currentName = threadNames.get(0);
+ String firstName = currentName;
+ String threadPrefix = currentName.substring( 0, currentName.indexOf("##")).trim();
+ // Length of the deadlock chain is (threadNums.size() - 1) since the first thread repeats to complete the chain.
+ System.err.println("Checking deadlock chain for \"" + threadPrefix + "\" threads that is " + (threadNums.size() - 1) + " threads long");
+ for( int i = 1; i < threadNums.size(); i++ ) {
+ int nextThread = threadNums.get(i);
+ String nextThreadName = threadNames.get(i);
+ if( nextThread != currentThread + 1 && nextThread != 0 ) {
+ System.err.println("Threads out of order: " + threadNames.get(i) + " after " + currentThread );
+ passed &= false;
+ break;
+ }
+ if( !nextThreadName.startsWith(threadPrefix)) {
+ System.err.println("Wrong thread type: " + threadNames.get(i) + " does not start with " + currentThread );
+ passed &= false;
+ break;
+ }
+ currentThread = nextThread;
+ currentName = nextThreadName;
+ }
+ if( firstThread == currentThread ) {
+ System.err.println("Complete thread cycle found, confirmed deadlock for " + threadPrefix + " threads" );
+ }
+ System.err.println("------------");
+
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ System.exit(1);
+ }
+ if( deadlockCount == expectedDeadlocks ) {
+ passed &= true;
+ }
+
+ return passed;
+ }
+
+ // Wrap this up as it's worth trimming the whitespace off the start of each jdmpview line.
+ private static String readLine(BufferedReader in) throws IOException {
+ String line = in.readLine();
+ return line!=null?line.trim():null;
+ }
+
+ public static int getThreadNumber(String threadName) {
+ // Pull the thread number out of a name that looks like:
+ // Deadlock Thread ##6##
+ int openQuote = -1;
+ int closeQuote = -1;
+ openQuote = threadName.indexOf("##");
+ closeQuote = threadName.indexOf("##", openQuote + 1);
+ if( openQuote > -1 && closeQuote > -1 ) {
+ String threadNo_string = threadName.substring(openQuote + 2, closeQuote);
+ int threadNo = Integer.parseInt(threadNo_string);
+ return threadNo;
+ } else {
+ return Integer.MIN_VALUE;
+ }
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/CreateJavaCore.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/CreateJavaCore.java
new file mode 100644
index 00000000000..5cf20f05702
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/CreateJavaCore.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_deadlock;
+
+import java.lang.Thread.State;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class CreateJavaCore {
+
+ private static DeadlockCreator[] deadlockCreators = { new Deadlock(), new JUCDeadlock(), new MixedDeadlock()};
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ boolean generateSystemCore = false;
+ if( args.length > 0 && args[0].equals("-core") ) {
+ // Only generate system core if that's what we're testing to save space.
+ // (We might as well always generate a javacore, they aren't big and would
+ // be useful for debugging problems with the core tests.)
+ generateSystemCore = true;
+ }
+
+ for( DeadlockCreator d: deadlockCreators ) {
+ // Even numbers only, otherwise the mixed deadlock creator won't work.
+ d.createDeadlockCycle(10);
+ }
+
+ com.ibm.jvm.Dump.JavaDump();
+ if( generateSystemCore ) {
+ com.ibm.jvm.Dump.SystemDump();
+ }
+ // We've deliberately deadlocked a bunch of threads.
+ // Don't wait for them before quitting.
+ System.exit(0);
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/Deadlock.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/Deadlock.java
new file mode 100644
index 00000000000..9c7fd5a7f1f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/Deadlock.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/package com.ibm.dump.tests.javacore_deadlock;
+
+import java.lang.Thread.State;
+
+public class Deadlock implements DeadlockCreator {
+
+ /**
+ * Create a chain of deadlocked threads.
+ */
+ public void createDeadlockCycle(int threadCount) {
+ Thread[] threads = new Thread[threadCount];
+
+ LockObject[] locks = new LockObject[threadCount];
+ for( int i = 0; i < threadCount; i++ ) {
+ locks[i] = new LockObject();
+ }
+
+ for( int i = 0; i < threadCount; i++ ) {
+ threads[i] = new Thread(new DeadlockThread(locks[i%threadCount], locks[(i+1)%threadCount]));
+ threads[i].setName("Deadlock Thread ##" + i + "##");
+ }
+
+ for( int i = 0; i < threadCount; i++ ) {
+ threads[i].start();
+ }
+
+ boolean deadlocked = false;
+ while(!deadlocked) {
+ deadlocked = true;
+ for( int i = 0; i < threads.length; i++ ) {
+ deadlocked &= threads[i].getState() == State.BLOCKED;
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ System.err.println(this.getClass().getSimpleName() + ": Should be able to take dump now, threads should be deadlocked.");
+ }
+
+ private static class LockObject {
+ public volatile boolean taken = false;
+ }
+
+ private static class DeadlockThread implements Runnable {
+
+ LockObject prev;
+ LockObject next;
+
+ public DeadlockThread(LockObject lastLock, LockObject nextLock ) {
+ prev = lastLock;
+ next = nextLock;
+ }
+
+ public void run() {
+ synchronized (prev) {
+ prev.taken = true;
+ System.out.println("Thread " + Thread.currentThread().getName() + " has last lock");
+ while( next.taken == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Thread " + Thread.currentThread().getName() + " attempting to get second lock");
+ synchronized (next) {
+ next.taken = true;
+ System.out.println("Thread " + Thread.currentThread().getName() + " has both locks");
+ }
+ }
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/DeadlockCreator.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/DeadlockCreator.java
new file mode 100644
index 00000000000..1b151a96593
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/DeadlockCreator.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_deadlock;
+
+public interface DeadlockCreator {
+
+ /**
+ * Creates a group of threads and gets them into a deadlocked state
+ * before returning. (When the method returns the threads should be
+ * started and deadlocked.)
+ * @param threads the number of threads to start in the cycle.
+ */
+ public void createDeadlockCycle(int threads);
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/JUCDeadlock.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/JUCDeadlock.java
new file mode 100644
index 00000000000..bdbc4e8f54e
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/JUCDeadlock.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_deadlock;
+
+import java.lang.Thread.State;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class JUCDeadlock implements DeadlockCreator {
+
+ final static int DEFAULT_THREADS = 10;
+
+ /**
+ * Create a chain of deadlocked threads.
+ * @param args
+ */
+ public void createDeadlockCycle(int threadCount) {
+ Thread[] threads = new Thread[threadCount];
+
+ ReentrantLock[] locks = new ReentrantLock[threadCount];
+ for( int i = 0; i < threadCount; i++ ) {
+ locks[i] = new ReentrantLock();
+ }
+
+ for( int i = 0; i < threadCount; i++ ) {
+ threads[i] = new Thread(new DeadlockThread(locks[i%threadCount], locks[(i+1)%threadCount]));
+ threads[i].setName("java.util.concurrent Deadlock Thread ##" + i + "##");
+ }
+
+ for( int i = 0; i < threadCount; i++ ) {
+ threads[i].start();
+ }
+
+ boolean deadlocked = false;
+ while(!deadlocked) {
+ deadlocked = true;
+ for( int i = 0; i < locks.length; i++ ) {
+ deadlocked &= locks[i].isLocked();
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ System.err.println(this.getClass().getSimpleName() + ": Should be able to take dump now, threads should be deadlocked.");
+ }
+
+ private static class LockObject {
+ public volatile boolean taken = false;
+ }
+
+ private static class DeadlockThread implements Runnable {
+
+ ReentrantLock prev;
+ ReentrantLock next;
+
+ public DeadlockThread(ReentrantLock lastLock, ReentrantLock nextLock ) {
+ prev = lastLock;
+ next = nextLock;
+ }
+
+ public void run() {
+ prev.lock();
+ try {
+ System.out.println("Thread " + Thread.currentThread().getName() + " has last lock");
+ while( next.isLocked() == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Thread " + Thread.currentThread().getName() + " attempting to get second lock");
+ next.lock();
+ try {
+ System.out.println("Thread " + Thread.currentThread().getName() + " has both locks");
+ } finally {
+ next.unlock();
+ }
+ } finally {
+ prev.unlock();
+ }
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/MixedDeadlock.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/MixedDeadlock.java
new file mode 100644
index 00000000000..02d485158e9
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_deadlock/MixedDeadlock.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_deadlock;
+
+import java.lang.Thread.State;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class MixedDeadlock implements DeadlockCreator {
+
+ final static int DEFAULT_THREADS = 10;
+
+ /**
+ * Create a chain of deadlocked threads.
+ * @param args
+ */
+ public void createDeadlockCycle(int threadCount) {
+ int lockCount = threadCount / 2;
+ Thread[] threads = new Thread[threadCount];
+
+ ReentrantLock[] jucLocks = new ReentrantLock[threadCount];
+ for( int i = 0; i < lockCount; i++ ) {
+ jucLocks[i] = new ReentrantLock();
+ }
+ LockObject[] objectLocks = new LockObject[threadCount];
+ for( int i = 0; i < lockCount; i++ ) {
+ objectLocks[i] = new LockObject();
+ }
+
+ for( int i = 0; i < threadCount; i++ ) {
+ if( (i % 2) == 0 ) {
+ threads[i] = new Thread(new DeadlockThreadEven(jucLocks[i%lockCount], objectLocks[(i+1)%lockCount]));
+ } else {
+ threads[i] = new Thread(new DeadlockThreadOdd(objectLocks[i%lockCount], jucLocks[(i+1)%lockCount]));
+ }
+ threads[i].setName("Mixed Deadlock Thread ##" + i + "##");
+ }
+
+ for( int i = 0; i < threadCount; i++ ) {
+ threads[i].start();
+ }
+
+ boolean deadlocked = false;
+ while(!deadlocked) {
+ deadlocked = true;
+ for( int i = 0; i < threads.length; i++ ) {
+ if( i % 2 == 0 ) {
+ deadlocked &= threads[i].getState() == State.BLOCKED;
+ } else {
+ deadlocked &= jucLocks[i%lockCount].isLocked();
+ }
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ System.err.println(this.getClass().getSimpleName() + ": Should be able to take dump now, threads should be deadlocked.");
+ }
+
+ private static class LockObject {
+ public volatile boolean taken = false;
+ }
+
+ private static class DeadlockThreadEven implements Runnable {
+
+ ReentrantLock prev;
+ LockObject next;
+
+ public DeadlockThreadEven(ReentrantLock lastLock, LockObject nextLock ) {
+ prev = lastLock;
+ next = nextLock;
+ }
+
+ public void run() {
+ prev.lock();
+ try {
+ System.out.println("Thread: " + Thread.currentThread().getName() + " has last lock");
+ while( next.taken == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Thread: " + Thread.currentThread().getName() + " attempting to get second lock");
+ synchronized (next) {
+ next.taken = true;
+ System.out.println("Thread: " + Thread.currentThread().getName() + " has both locks");
+ }
+ } finally {
+ prev.unlock();
+ }
+ }
+ }
+
+ private static class DeadlockThreadOdd implements Runnable {
+
+ LockObject prev;
+ ReentrantLock next;
+
+ public DeadlockThreadOdd(LockObject lastLock, ReentrantLock nextLock ) {
+ prev = lastLock;
+ next = nextLock;
+ }
+
+ public void run() {
+ synchronized(prev) {
+ prev.taken = true;
+ System.out.println("Thread " + Thread.currentThread().getName() + " has last lock");
+ while( next.isLocked() == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Thread " + Thread.currentThread().getName() + " attempting to get second lock");
+ next.lock();
+ try {
+ System.out.println("Thread " + Thread.currentThread().getName() + " has both locks");
+ } finally {
+ next.unlock();
+ }
+ }
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/CheckJavaCore.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/CheckJavaCore.java
new file mode 100644
index 00000000000..e58e5b1e3cb
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/CheckJavaCore.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * This class check a javacore for a few pre-setup deadlock cycles.
+ *
+ * @author hhellyer
+ *
+ */
+public class CheckJavaCore {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.err.println("An input javacore is required to check.");
+ System.exit(1);
+ }
+ String fileName = args[0];
+
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(fileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + fileName + " not found.");
+ System.exit(1);
+ }
+ if (in == null) {
+ System.err.println("Failed to open file: " + fileName);
+ System.exit(1);
+ }
+
+ // We get the expected results by re-running the threads.
+ CreateJavaCore.setupThreads();
+
+ boolean passed = true;
+
+ passed &= checkThreadSection(in);
+
+ if( passed ) {
+ System.err.println("Test passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Test failed.");
+ System.exit(1);
+ }
+ }
+
+ private static boolean checkThreadSection(BufferedReader in) {
+ String line;
+ boolean passed = true;
+
+ Map threadsToEntries = CreateJavaCore.threadsToEntries;
+ final int threadsToCheck = threadsToEntries.size();
+ int threadsChecked = 0;
+
+ // Fast forward to 1XMTHDINFO Thread Details
+ // (Fail if we don't find it.)
+ try {
+ line = in.readLine();
+ while( line != null ) {
+ // Look for "3XMTHREADINFO " (with space) so we don't match "3XMTHREADINFO1 2 or 3"
+ while (line != null && !line.startsWith("3XMTHREADINFO ")) {
+ line = in.readLine();
+ }
+ if( line == null ) {
+ System.err.println("Null line");
+ passed = false;
+ break;
+ }
+
+ String threadName = getQuotedThreadName(line);
+ line = in.readLine();
+ StackCreator stackCreator = threadsToEntries.get(threadName);
+ if( stackCreator == null ) {
+ // Not one of our threads, skip this one.
+ continue;
+ }
+ System.err.println("Checking " + threadName);
+ Stack entryStack = new Stack();
+ entryStack.addAll(stackCreator.getEntryRecords());
+ EntryRecord nextEntry = entryStack.pop();
+ // Walk the thread stack until we get to the end, look for "NULL"
+ while (line != null && !line.startsWith("NULL")) {
+ if( line != null && nextEntry != null && line.startsWith("4XESTACKTRACE") && line.contains(nextEntry.getMethodName() )) {
+ // Get the method name, see if it's the next one we are looking for.
+ // (Not all entries in the stack will have entry records.)
+ // System.err.println("Found: " + line + " looking for " + nextEntry.getMethodName());
+
+ // Next line should contain an entry record, read and check.
+ line = in.readLine();
+ while( line.startsWith("5XESTACKTRACE")) {
+ if( !line.startsWith("5XESTACKTRACE (entered lock: " + nextEntry.getLockName())) {
+ System.err.println("Fail - Didn't find entry record for " + nextEntry.getMethodName());
+ System.err.println("Expected: 5XESTACKTRACE (entered lock: " + nextEntry.getLockName());
+ // System.err.println("Line: " + line);
+ } else if( !line.contains("entry count: " + nextEntry.getEntryCount() + ")")) {
+ System.err.println("Fail - Didn't find expected enter count " + "entry count: " + nextEntry.getEntryCount() + ")");
+ // System.err.println("Line: " + line);
+ } else {
+ // System.err.println("Found expected entry.");
+ }
+ nextEntry = entryStack.isEmpty()?null:entryStack.pop();
+ line = in.readLine();
+ }
+ } else {
+ line = in.readLine();
+ }
+ }
+ threadsChecked++;
+ if( !entryStack.isEmpty() ) {
+ System.err.println("Failed to find all lock entry records for " + threadName);
+ passed = false;
+ } else {
+ System.err.println("Found correct lock entry records for " + threadName);
+ }
+ System.err.println("------------");
+ if( threadsChecked == threadsToCheck ) {
+ break; // Finished. (There will be other threads but we are only interested in ours.)
+ }
+
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ System.exit(1);
+ }
+
+ return passed;
+ }
+
+ /**
+ * Given a string, returns the contents of the first quoted string.
+ * (Which in java cores is generally the thread name.
+ * @param line
+ * @return
+ */
+ public static String getQuotedThreadName(String line) {
+ // Pull the thread name out of a line that looks like:
+ // 3XMTHREADINFO "main" J9VMThread:0x00129100, j9thread_t:0x002B5A30, java/lang/Thread:0x00DDC4F8, state:R, prio=5
+ // There are threads that don't have quotes, but they aren't Java threads so we aren't
+ // interested here.
+ int openQuote = -1;
+ int closeQuote = -1;
+ openQuote = line.indexOf('"');
+ closeQuote = line.indexOf('"', openQuote + 1);
+ if( openQuote > -1 && closeQuote > -1 ) {
+ String threadName = line.substring(openQuote + 1, closeQuote);
+ return threadName;
+ } else {
+ return null;
+ }
+ }
+
+ public static int getThreadNumber(String threadName) {
+ // Pull the thread number out of a name that looks like:
+ // Deadlock Thread ##6##
+ int openQuote = -1;
+ int closeQuote = -1;
+ openQuote = threadName.indexOf("##");
+ closeQuote = threadName.indexOf("##", openQuote + 1);
+ if( openQuote > -1 && closeQuote > -1 ) {
+ String threadNo_string = threadName.substring(openQuote + 2, closeQuote);
+ int threadNo = Integer.parseInt(threadNo_string);
+ return threadNo;
+ } else {
+ return Integer.MIN_VALUE;
+ }
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/CreateJavaCore.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/CreateJavaCore.java
new file mode 100644
index 00000000000..63a038110ba
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/CreateJavaCore.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Lock context checks:
+ *
+ * Enter a lock. Check we enter expected lock in expected method.
+ *
+ * Enter a lock twice. Check lock count incremented twice.
+ *
+ * Enter a lock n times going down a stack. Check highest entry count matches
+ * entry count in monitor section.
+ *
+ * Enter n different locks in 1 frame. Check correct number of entries take
+ * place.
+ *
+ * Enter 3 different locks, twice, in mixed up order. Check only 1 record per
+ * lock. e.g sync(a), sync(b), sync(c), sync(a), sync(b), sync(c)
+ *
+ * @author hhellyer
+ *
+ */
+public class CreateJavaCore {
+
+ private static StackCreator[] stackCreator = { new SimpleEnter(), new EnterTwice(), new EnterInStack(), new EnterInSequence() };
+
+ protected static Map threadsToEntries = new HashMap();
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ boolean generateSystemCore = false;
+ if( args.length > 0 && args[0].equals("-core") ) {
+ // Only generate system core if that's what we're testing to save space.
+ // (We might as well always generate a javacore, they aren't big and would
+ // be useful for debugging problems with the core tests.)
+ generateSystemCore = true;
+ }
+
+ setupThreads();
+
+ com.ibm.jvm.Dump.JavaDump();
+ if( generateSystemCore ) {
+ com.ibm.jvm.Dump.SystemDump();
+ }
+ // We've deliberately deadlocked a bunch of threads.
+ // Don't wait for them before quitting.
+ System.exit(0);
+ }
+
+ public static void setupThreads() {
+ for( StackCreator s: stackCreator ) {
+ Thread t = new Thread( s );
+ t.start();
+ threadsToEntries.put( s.getClass().getSimpleName() + " Thread", s);
+ }
+ boolean ready = false;
+ while( !ready ) {
+ ready = true;
+ for( StackCreator s: stackCreator ) {
+ ready &= s.isReady();
+ }
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterInSequence.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterInSequence.java
new file mode 100644
index 00000000000..f44c468eeff
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterInSequence.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+
+public class EnterInSequence extends StackCreator {
+
+ private boolean ready = false;
+
+ private class LockA {}
+ private class LockB {}
+ private class LockC {}
+
+ private LockA lockA = new LockA();
+ private LockB lockB = new LockB();
+ private LockC lockC = new LockC();
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName(this.getClass().getSimpleName() + " Thread");
+ enterMethod();
+ }
+
+ private void enterMethod() {
+
+ // A silly sequence of locking to confirm we only get one enter record (counting 2 enters)
+ // for each of these locks.
+ synchronized (lockA) {
+ synchronized (lockB) {
+ synchronized (lockC) {
+ synchronized (lockA) {
+ synchronized (lockB) {
+ synchronized (lockC) {
+ try {
+ entryRecords.add(new EntryRecord(lockA.getClass().getName(), 2));
+ entryRecords.add(new EntryRecord(lockB.getClass().getName(), 2));
+ entryRecords.add(new EntryRecord(lockC.getClass().getName(), 2));
+ ready = true; // We have taken our own lock.
+ Thread.sleep(1000*60*60); // Sleep for an hour. (The test will exit before then.)
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isReady() {
+ return ready;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterInStack.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterInStack.java
new file mode 100644
index 00000000000..2599f453a97
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterInStack.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+public class EnterInStack extends StackCreator {
+
+ private boolean ready = false;
+
+ private class Lock {}
+
+ Lock lock = new Lock();
+
+ private static final int stackDepth = 10;
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName(this.getClass().getSimpleName() + " Thread");
+ enterMethod(stackDepth);
+ }
+
+ private void enterMethod(int depth) {
+ try {
+ synchronized (lock) {
+ entryRecords.add(new EntryRecord(lock.getClass().getName(), stackDepth - depth + 1));
+ if( depth <= 1 ) {
+ ready = true; // We have taken our own lock.
+ Thread.sleep(1000*60*60); // Sleep for an hour. (The test will exit before then.)
+ } else {
+ enterMethod(depth - 1);
+ }
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+
+ @Override
+ public boolean isReady() {
+ return ready;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterTwice.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterTwice.java
new file mode 100644
index 00000000000..52484e9f248
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EnterTwice.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+public class EnterTwice extends StackCreator {
+
+ private boolean ready = false;
+
+ private class Lock {}
+
+ Lock lock = new Lock();
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName(this.getClass().getSimpleName() + " Thread");
+ enterMethod();
+ }
+
+ private void enterMethod() {
+ synchronized (lock) {
+ try {
+ synchronized (lock) {
+ entryRecords.add(new EntryRecord(lock.getClass().getName(), 2));
+ ready = true; // We have taken our own lock.
+ Thread.sleep(1000*60*60); // Sleep for an hour. (The test will exit before then.)
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ @Override
+ public boolean isReady() {
+ return ready;
+ }
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EntryRecord.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EntryRecord.java
new file mode 100644
index 00000000000..a387a32bb3f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/EntryRecord.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+/**
+ * Class to hold the *expected* entry records we expect to find in the javacore.
+ *
+ * @author hhellyer
+ *
+ */
+public class EntryRecord {
+
+ private int entryCount;
+ private StackTraceElement stackEntry;
+ private String lockName;
+
+ public EntryRecord( String lockName, int entryCount ) {
+ this.entryCount = entryCount;
+ this.lockName = lockName.replace('.', '/');;
+ // Get the stack frame for the calling method.
+ // (Yes this is evil, this is just a testcase.)
+ this.stackEntry = (new Throwable()).getStackTrace()[1];
+ }
+
+ public String getMethodName() {
+ String className = stackEntry.getClassName().replace('.', '/');
+ return className + "." +stackEntry.getMethodName();
+ }
+
+ public String getLockName() {
+ return lockName;
+ }
+
+ public int getEntryCount() {
+ return entryCount;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/SimpleEnter.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/SimpleEnter.java
new file mode 100644
index 00000000000..9ffbbf1eb42
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/SimpleEnter.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+public class SimpleEnter extends StackCreator {
+
+ private boolean ready = false;
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName(this.getClass().getSimpleName() + " Thread");
+ synchronziedMethod();
+ }
+
+ private synchronized void synchronziedMethod() {
+
+ try {
+ entryRecords.add(new EntryRecord(this.getClass().getName(), 1));
+ ready = true; // We have taken our own lock.
+ Thread.sleep(1000*60*60); // Sleep for an hour. (The test will exit before then.)
+ } catch (InterruptedException e) {
+ }
+ }
+
+ @Override
+ public boolean isReady() {
+ return ready;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/StackCreator.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/StackCreator.java
new file mode 100644
index 00000000000..2f0df8b2e5a
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_lock_context/StackCreator.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_lock_context;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class StackCreator implements Runnable {
+
+ public abstract boolean isReady();
+
+ protected List entryRecords = new ArrayList();
+
+ public List getEntryRecords() {
+ return entryRecords;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_meminfo/ValidateMemInfo.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_meminfo/ValidateMemInfo.java
new file mode 100644
index 00000000000..cba23ac6dcf
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_meminfo/ValidateMemInfo.java
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_meminfo;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * Test application that reads a javacore and validates the MEMINFO section against !dumpallsegments
+ * debug extension output from a core file read by jdmpview.
+ *
+ * Usage:
+ * java com.ibm.memorycategories.ValidateMeminfo
+ *
+ * @author Richard Chamberlain
+ *
+ */
+public class ValidateMemInfo {
+
+ /**
+ * main()
+ *
+ * @param args - javacore and jdmpview !dumpallsegments output
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 2) {
+ System.err.println("Input javacore and jdmpview !dumpallsegments files are required.");
+ System.exit(1);
+ }
+ String javacoreFile = args[0];
+ String jdmpviewFile = args[1];
+
+ BufferedReader in1 = null;
+ BufferedReader in2 = null;
+ try {
+ in1 = new BufferedReader(new FileReader(javacoreFile));
+ in2 = new BufferedReader(new FileReader(jdmpviewFile));
+ } catch (FileNotFoundException e) {
+ System.err.println("File not found");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ if (in1 == null) {
+ System.err.println("Failed to open javacore file");
+ System.exit(1);
+ }
+ if (in2 == null) {
+ System.err.println("Failed to open jdmpview !dumpallsegments file");
+ System.exit(1);
+ }
+
+ boolean rc = compareMemInfo(in1, in2);
+
+ if (rc == true) {
+ System.err.println("Test passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Test failed.");
+ System.exit(1);
+ }
+ }
+
+
+ /*
+ * compareMemInfo()
+ *
+ * @param in1 javacore
+ * @param in2 jdmpview !dumpallsegments output
+ * @return true/false for pass/fail
+ */
+ private static boolean compareMemInfo(BufferedReader in1, BufferedReader in2) {
+ String line;
+
+ // First parse and validate the code cache memory segments in the javacore
+ long jcCodeCacheTotal = 0;
+ long jcCodeCacheAlloc = 0;
+ long jcCodeCacheFree = 0;
+
+ /* 2.6 VM and later:
+ * 1STSEGTYPE JIT Code Cache
+ * NULL segment start alloc end type size
+ * 1STSEGMENT 0x0000000002C9FCA8 0x000007FFDEE80000 0x000007FFDEE80000 0x000007FFDF080000 0x00000068 0x0000000000200000
+ * 1STSEGMENT 0x0000000002CDBD58 0x000007FFDF080000 0x000007FFDF080000 0x000007FFDF280000 0x00000068 0x0000000000200000
+ * 1STSEGMENT 0x0000000002CDBCA0 0x000007FFDF280000 0x000007FFDF280000 0x000007FFDF480000 0x00000068 0x0000000000200000
+ * 1STSEGMENT 0x0000000002CDBBE8 0x000007FFDF480000 0x000007FFDF480000 0x000007FFDF680000 0x00000068 0x0000000000200000
+ * NULL
+ * 1STSEGTOTAL Total memory: 8388608 (0x0000000000800000)
+ * 1STSEGINUSE Total memory in use: 0 (0x0000000000000000)
+ * 1STSEGFREE Total memory free: 8388608 (0x0000000000800000)
+ *
+ * 2.4 VM:
+ * 1STSEGTYPE JIT Code Cache
+ * NULL segment start alloc end type bytes
+ * 1STSEGMENT 000000000029E4C8 000007FFFF7A0000 000007FFFF80D9C0 000007FFFFFA0000 00000068 800000
+ */
+ try {
+ System.out.println("Parsing code cache memory segments in javacore:");
+ line = in1.readLine();
+ // Find the JIT Code Cache
+ while (line != null && !line.startsWith("1STSEGTYPE JIT Code Cache")) {
+ line = in1.readLine();
+ }
+
+ while ((line = in1.readLine()) != null ) {
+ if (line.startsWith("1STSEGMENT")) {
+ String[] values = line.split("[ ]+");
+ // Get the start, alloc and end values for this segment. The .substring(2) removes the 0x prfix
+ long start = Long.parseLong(values[2].substring(2), 16);
+ long alloc = Long.parseLong(values[3].substring(2), 16);
+ long end = Long.parseLong(values[4].substring(2), 16);
+ // System.out.println("seg values " + start + " " + alloc + " " + end + "\n");
+ jcCodeCacheTotal += end - start;
+ jcCodeCacheAlloc += alloc - start;
+ jcCodeCacheFree += end - alloc;
+ continue; // Processed this line.
+ } else if (line.startsWith("1STSEGTOTAL")) {
+ String[] values = line.split("[ ]+");
+ if (jcCodeCacheTotal == Long.parseLong(values[3], 10)) {
+ System.out.println("\tcorrect total");
+ } else {
+ System.out.println("\tincorrect total: " + jcCodeCacheTotal + " " + Long.parseLong(values[3], 10));
+ }
+ continue;
+ } else if (line.startsWith("1STSEGINUSE")) {
+ String[] values = line.split("[ ]+");
+ if (jcCodeCacheAlloc == Long.parseLong(values[5], 10)) {
+ System.out.println("\tcorrect in use total");
+ } else {
+ System.out.println("\tincorrect in use total: " + jcCodeCacheAlloc + " " + Long.parseLong(values[5], 10));
+ }
+ continue;
+ } else if (line.startsWith("1STSEGFREE")) {
+ String[] values = line.split("[ ]+");
+ if (jcCodeCacheFree == Long.parseLong(values[4], 10)) {
+ System.out.println("\tcorrect free total");
+ } else {
+ System.out.println("\tincorrect free total: " + jcCodeCacheFree + " " + Long.parseLong(values[4], 10));
+ }
+ break; // we are done
+ } else if (line.startsWith("NULL")) {
+ // ignore
+ } else {
+ System.err.println("Unexpected javacore line");
+ break;
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ return false;
+ }
+
+ // Now parse and validate the code cache segment information in the jdmpview output
+ long jdCodeCacheTotal = 0;
+ long jdCodeCacheAlloc = 0;
+ long jdCodeCacheFree = 0;
+ /*
+ * jit code segments - !j9memorysegmentlist 0x293e670
+ * +----------------+----------------+----------------+----------------+----------------+--------+
+ * | segment | start | warmAlloc | coldAlloc | end | size |
+ * +----------------+----------------+----------------+----------------+----------------+--------+
+ * 00000000029b9968 000007ffdee80000 000007ffdee83280 000007ffdf0602c0 000007ffdf080000 200000
+ * 0000000002946f18 000007ffdf080000 000007ffdf080020 000007ffdf260318 000007ffdf280000 200000
+ * 0000000002946e60 000007ffdf280000 000007ffdf280020 000007ffdf460318 000007ffdf480000 200000
+ * 0000000002946da8 000007ffdf480000 000007ffdf480020 000007ffdf660318 000007ffdf680000 200000
+ * +----------------+----------------+----------------+----------------+----------------+--------+
+ * Total memory: 0000000008388608 (0000000000800000)
+ * Total memory in use: 0000000000534232 (00000000000826d8)
+ * Total memory free: 0000000007854376 (000000000077d928)
+ */
+ try {
+ System.out.println("Parsing code cache memory segments in jdmpview output:");
+ line = in2.readLine();
+ // Find the JIT Code Cache
+ while (line != null && !line.startsWith("jit code segments")) {
+ line = in2.readLine();
+ }
+
+ while ((line = in2.readLine()) != null ) {
+ if (line.startsWith("Total memory:")) {
+ String[] values = line.split("[ ]+");
+ if (jdCodeCacheTotal == Long.parseLong(values[2], 10)) {
+ System.out.println("\tcorrect total");
+ } else {
+ System.out.println("\tincorrect total: " + jdCodeCacheTotal + " " + Long.parseLong(values[2], 10));
+ }
+ continue;
+ } else if (line.startsWith("Total memory in use:")) {
+ String[] values = line.split("[ ]+");
+ if (jdCodeCacheAlloc == Long.parseLong(values[4], 10)) {
+ System.out.println("\tcorrect in use total");
+ } else {
+ System.out.println("\tincorrect in use total: " + jdCodeCacheAlloc + " " + Long.parseLong(values[4], 10));
+ }
+ continue;
+ } else if (line.startsWith("Total memory free:")) {
+ String[] values = line.split("[ ]+");
+ if (jdCodeCacheFree == Long.parseLong(values[3], 10)) {
+ System.out.println("\tcorrect free total");
+ } else {
+ System.out.println("\tincorrect free total: " + jdCodeCacheFree + " " + Long.parseLong(values[3], 10));
+ }
+ break; // we are done
+ } else if (line.startsWith("+")) {
+ // header line, ignore
+ } else if (line.startsWith("|")) {
+ // header line, ignore
+ } else {
+ // Should be a data line. Note that the data lines have a leading space, so 'start' is at index=2
+ String[] values = line.split("[ ]+");
+ long start = Long.parseLong(values[2], 16);
+ long warm = Long.parseLong(values[3], 16);
+ long cold = Long.parseLong(values[4], 16);
+ long end = Long.parseLong(values[5], 16);
+ System.out.println("\tsegment values " + start + " " + warm + " " + cold + " " + end);
+ jdCodeCacheTotal += end - start;
+ jdCodeCacheAlloc += (warm - start) + (end - cold);
+ jdCodeCacheFree += cold - warm;
+ continue; // Processed this line.
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading jdmpview output file.");
+ return false;
+ }
+
+ // Finally, compare the code cache segment totals from the javacore with those from the jdmpview output.
+ System.out.println("Code cache (javacore) total: " + jcCodeCacheTotal + " alloc: " + jcCodeCacheAlloc + " free: " + jcCodeCacheFree);
+ System.out.println("Code cache (coredump) total: " + jdCodeCacheTotal + " alloc: " + jdCodeCacheAlloc + " free: " + jdCodeCacheFree);
+ if (jcCodeCacheTotal != jdCodeCacheTotal) {
+ System.err.println("Test failed: code cache total memory validation failed");
+ return false;
+ }
+ // The JIT may have allocated or freed memory in the time interval between the javacore and
+ // system dumps. So allow for a +/- 10% variation between the corresponding code cache values.
+ if (Math.abs(jcCodeCacheAlloc - jdCodeCacheAlloc) > jcCodeCacheTotal/10) {
+ System.err.println("Test failed: code cache allocated memory validation failed");
+ return false;
+ }
+ if (Math.abs(jcCodeCacheFree - jdCodeCacheFree) > jcCodeCacheTotal/10) {
+ System.err.println("Test failed: code cache free memory validation failed");
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CheckJavaCore.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CheckJavaCore.java
new file mode 100644
index 00000000000..acdd84d524e
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CheckJavaCore.java
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_thread;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class check a javacore for a set of thread with known names and checks
+ * that they are correctly marked as blocked by other threads.
+ *
+ * @author hhellyer
+ *
+ */
+public class CheckJavaCore {
+
+ private static final String THREADINFO_TAG = "3XMTHREADINFO ";
+
+ private static final String THREADBLOCK_TAG = "3XMTHREADBLOCK";
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.err.println("An input javacore is required to check.");
+ System.exit(1);
+ }
+ String fileName = args[0];
+
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(fileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + fileName + " not found.");
+ System.exit(1);
+ }
+ if (in == null) {
+ System.err.println("Failed to open file: " + fileName);
+ System.exit(1);
+ }
+
+ boolean passed = true;
+
+ passed &= checkThreadSection(in);
+ try {
+ in = new BufferedReader(new FileReader(fileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + fileName + " not found on second read.");
+ System.exit(1);
+ }
+ System.err.println();
+ passed &= checkMonitorSection(in);
+ if( passed ) {
+ System.err.println("Test passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Test failed.");
+ System.exit(1);
+ }
+ }
+
+
+ /*
+ * 2LKMONINUSE sys_mon_t:0x00007F6B903C5E98 infl_mon_t: 0x00007F6B903C5F10:
+ * 3LKMONOBJECT java/lang/String@0x00007F6B68CFB210: Flat locked by "BlockedOnSynchronized: lock owner" (0x00007F6B14007400), entry count 1
+ * 3LKWAITERQ Waiting to enter:
+ * 3LKWAITER "BlockedOnSynchronized: waiting thread" (0x00007F6B1400EA00)
+ */
+ private static boolean checkMonitorSection(BufferedReader in) {
+ String line;
+ // Increment this every time we find one of our threads.
+ int lockCount = 0;
+ boolean passed = true;
+ Map threadNameToCreator = new HashMap();
+
+ System.err.println("Checking Monitors");
+
+ for(CoreThreadCreator job: CoreThreadCreator.setupJobs ) {
+ if( job.isSynchronizedLock() ) {
+ threadNameToCreator.put(job.getThreadNameToCheck(), job);
+ }
+ }
+ final int expectedLockCount = threadNameToCreator.size();
+
+ try {
+ line = in.readLine();
+ while (line != null) {
+ String lockOwnerLine = null;
+ String blockingThreadName = null;
+ String blockedThreadName = null;
+ if( !line.startsWith("2LKMONINUSE")) {
+ // Skip boring lines.
+ line = in.readLine();
+ continue;
+ }
+ line = in.readLine();
+ if( line.startsWith("3LKMONOBJECT")) {
+ getQuotedThreadName(line);
+ blockingThreadName = getQuotedThreadName(line);
+ if( blockingThreadName == null ) {
+ blockingThreadName = "";
+ }
+ lockOwnerLine = line;
+ }
+ line = in.readLine(); // 3LKNOTIFYQ, 3LKWAITERQ
+ line = in.readLine(); // 3LKWAITNOTIFY, 3LKWAITER
+ if( line.startsWith("3LKWAIT")) {
+ blockedThreadName = getQuotedThreadName(line);
+ }
+
+ CoreThreadCreator threadCreator = (CoreThreadCreator)threadNameToCreator.remove(blockedThreadName);
+ if( threadCreator == null ) {
+ line = in.readLine();
+ System.err.println("Found no entry for " + blockedThreadName);
+ continue;
+ }
+ System.err.println("Found expected lock for - \"" + threadCreator.getThreadNameToCheck() + "\"");
+ if( !blockingThreadName.equals(threadCreator.getOwnerName())){
+ System.err.println("Did not find expected owning thread \"" + threadCreator.getOwnerName() + "\"");
+ System.err.println("*** FAIL ***");
+ passed = false;
+ } else {
+ System.err.println("Confirmed " + blockingThreadName + " held the lock blocking " + blockedThreadName);
+ System.err.println("Pass");
+ }
+ lockCount++;
+
+
+ line = in.readLine();
+ System.err.println("------------");
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ System.exit(1);
+ }
+ System.err.println("Checked " + lockCount + " blocked threads out of " + expectedLockCount + " expected blocked threads");
+ if( threadNameToCreator.size() != 0 ) {
+ System.err.println("*** FAIL ***");
+ passed = false;
+ System.err.println("Failed to find all expected threads blocked: ");
+ for( Object key: threadNameToCreator.keySet() ) {
+ System.err.println("Missing thread: \"" + key + "\"");
+ }
+ } else {
+ System.err.println("Found and checked all expected threads.");
+ }
+ return passed;
+ }
+
+ private static boolean checkThreadSection(BufferedReader in) {
+ String line;
+ // Increment this every time we find one of our threads.
+ int threadCount = 0;
+ boolean passed = true;
+ Map threadNameToCreator = new HashMap();
+
+ System.err.println("Checking Thread Blockers");
+
+ for(CoreThreadCreator job: CoreThreadCreator.setupJobs ) {
+ threadNameToCreator.put(job.getThreadNameToCheck(), job);
+ }
+ final int expectedThreadCount = threadNameToCreator.size();
+
+ try {
+ line = in.readLine();
+ while (line != null) {
+ if( !line.startsWith(THREADINFO_TAG)) {
+ // Skip boring lines.
+ line = in.readLine();
+ continue;
+ }
+ String threadName = getQuotedThreadName(line);
+ CoreThreadCreator threadCreator = (CoreThreadCreator)threadNameToCreator.remove(threadName);
+ if( threadName == null || threadCreator == null ) {
+ line = in.readLine();
+ continue;
+ }
+ System.err.println("Found expected thread - \"" + threadCreator.getThreadNameToCheck() + "\"");
+ threadCount++;
+ while( !line.startsWith(THREADBLOCK_TAG) ) {
+ // If we reach NULL we know we've gone off the end of this thread and should fail.
+ if( line.startsWith("NULL")) {
+ break;
+ }
+ line = in.readLine();
+ }
+ if( !line.startsWith(THREADBLOCK_TAG)) {
+ System.err.println("*** FAIL ***");
+ passed = false;
+ System.err.println("No " + THREADBLOCK_TAG + " line for thread " + threadName);
+ System.err.println("Fail");
+ System.err.println("------------");
+ // This isn't a blocked thread so carry on.
+ line = in.readLine();
+ continue;
+ }
+ System.err.println("Blocked line: " + line);
+ if( threadCreator.checkBlockingLine(line) ) {
+ System.err.println("Pass");
+ } else {
+ System.err.println("*** FAIL ***");
+ passed = false;
+ }
+ System.err.println("------------");
+ line = in.readLine();
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ System.exit(1);
+ }
+ System.err.println("Checked " + threadCount + " threads out of " + expectedThreadCount + " expected threads");
+ if( threadNameToCreator.size() != 0 ) {
+ passed = false;
+ System.err.println("Failed to find all expected threads: ");
+ for( Object key: threadNameToCreator.keySet() ) {
+ System.err.println("Missing thread: \"" + key + "\"");
+ }
+ } else {
+ System.err.println("Found and checked all expected threads.");
+ }
+ return passed;
+ }
+
+ /**
+ * Given a string, returns the contents of the first quoted string.
+ * (Which in java cores is generally the thread name.
+ * @param line
+ * @return
+ */
+ public static String getQuotedThreadName(String line) {
+ // Pull the thread name out of a line that looks like:
+ // 3XMTHREADINFO "main" J9VMThread:0x00129100, j9thread_t:0x002B5A30, java/lang/Thread:0x00DDC4F8, state:R, prio=5
+ // There are threads that don't have quotes, but they aren't Java threads so we aren't
+ // interested here.
+ int openQuote = -1;
+ int closeQuote = -1;
+ openQuote = line.indexOf('"');
+ closeQuote = line.indexOf('"', openQuote + 1);
+ if( openQuote > -1 && closeQuote > -1 ) {
+ String threadName = line.substring(openQuote + 1, closeQuote);
+ return threadName;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CheckJdmpviewInfoThread.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CheckJdmpviewInfoThread.java
new file mode 100644
index 00000000000..c14debdda6f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CheckJdmpviewInfoThread.java
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_thread;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class check a javacore for a set of thread with known names and checks
+ * that they are correctly marked as blocked by other threads.
+ *
+ * @author hhellyer
+ *
+ */
+public class CheckJdmpviewInfoThread {
+
+ private static final String THREADINFO_TAG = " name: ";
+
+ private static final String[] THREADBLOCK_TAGS = {" parked on: "," waiting to be notified on: "," waiting to enter: " };
+
+// private static Map threadNameToCreator = new HashMap();
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.err.println("An input file is required to check.");
+ System.exit(1);
+ }
+ String fileName = args[0];
+
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(fileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + fileName + " not found.");
+ System.exit(1);
+ }
+ if (in == null) {
+ System.err.println("Failed to open file: " + fileName);
+ System.exit(1);
+ }
+
+ boolean passed = true;
+
+ passed &= checkThreadSection(in);
+ try {
+ in = new BufferedReader(new FileReader(fileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + fileName + " not found on second read.");
+ System.exit(1);
+ }
+ System.err.println();
+ passed &= checkMonitorSection(in);
+ if( passed ) {
+ System.err.println("Test passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Test failed.");
+ System.exit(1);
+ }
+ }
+
+ /*
+ * 2LKMONINUSE sys_mon_t:0x00007F6B903C5E98 infl_mon_t: 0x00007F6B903C5F10:
+ * 3LKMONOBJECT java/lang/String@0x00007F6B68CFB210: Flat locked by "BlockedOnSynchronized: lock owner" (0x00007F6B14007400), entry count 1
+ * 3LKWAITERQ Waiting to enter:
+ * 3LKWAITER "BlockedOnSynchronized: waiting thread" (0x00007F6B1400EA00)
+ */
+ private static boolean checkMonitorSection(BufferedReader in) {
+ String line;
+ // Increment this every time we find one of our threads.
+ int lockCount = 0;
+ boolean passed = true;
+ Map threadNameToCreator = new HashMap();
+
+ System.err.println("Checking Monitors");
+
+ for(CoreThreadCreator job: CoreThreadCreator.setupJobs ) {
+ // The parked thread isn't actual locked on anything, it's just parked.
+ if( !(job instanceof CoreThreadCreator.ParkedThread) ) {
+ threadNameToCreator.put(job.getThreadNameToCheck(), job);
+ }
+ }
+ final int expectedLockCount = threadNameToCreator.size();
+
+ try {
+ line = in.readLine();
+ // Fast forward through the system monitors.
+ while (line != null && !line.startsWith("Object Locks in use")) {
+ line = in.readLine();
+ }
+
+ /* Now looking at something like:
+ * java/lang/String@0x7fbb7cadba80
+ * owner thread id: 20107 name: WaitingOnSynchronized: lock owner
+ * waiting thread id: 20094 name: WaitingOnSynchronized: waiting thread
+ */
+ String lock = null;
+ String blockingThreadName = "";
+ String blockedThreadName = null;
+ while ( (line = in.readLine()) != null ) {
+ if( line.contains("@")) {
+ // New lock.
+ lock = line;
+ blockingThreadName = "";
+ blockedThreadName = null;
+ continue; // Processed this line.
+ }
+ if( line.contains("owner thread id:")) {
+ blockingThreadName = line.substring( line.indexOf("name: ") + "name: ".length());
+ continue; // Processed this line.
+ }
+ if( line.contains("waiting thread id:")) {
+ blockedThreadName = line.substring( line.indexOf("name: ") + "name: ".length());
+ // Do checks here now we know the id of the blocked thread.
+ CoreThreadCreator threadCreator = (CoreThreadCreator)threadNameToCreator.remove(blockedThreadName);
+ if( threadCreator == null ) {
+ System.err.println("Found no entry for " + blockedThreadName);
+ continue; // Processed this line.
+ }
+ System.err.println("Found expected lock for - \"" + threadCreator.getThreadNameToCheck() + "\"");
+ if( !blockingThreadName.equals(threadCreator.getOwnerName()) ){
+ System.err.println("Did not find expected owning thread \"" + threadCreator.getOwnerName() + "\"");
+ System.err.println("Found: \"" + blockingThreadName + "\"");
+ System.err.println("*** FAIL ***");
+ passed = false;
+ System.err.println("------------");
+ } else {
+ System.err.println("Confirmed " + blockingThreadName + " held the lock blocking " + blockedThreadName);
+ System.err.println("Pass");
+ lockCount++;
+ System.err.println("------------");
+ }
+ continue;
+ }
+ if( line.startsWith("java.util.concurrent locks in use")) {
+ break; // Done with monitors, juc locks next.
+ }
+ }
+ while ( (line = in.readLine()) != null ) {
+ if( line.contains("@")) {
+ // New lock.
+ lock = line;
+ blockingThreadName = "";
+ blockedThreadName = null;
+ continue; // Processed this line.
+ }
+ if( line.contains("locked by java thread id:")) {
+ blockingThreadName = line.substring( line.indexOf("name: ") + "name: ".length());
+ continue; // Processed this line.
+ }
+ if( line.contains("waiting thread id:")) {
+ blockedThreadName = line.substring( line.indexOf("name: ") + "name: ".length());
+ // Do checks here now we know the id of the blocked thread.
+ CoreThreadCreator threadCreator = (CoreThreadCreator)threadNameToCreator.remove(blockedThreadName);
+ if( threadCreator == null ) {
+ System.err.println("Found no entry for " + blockedThreadName);
+ continue; // Processed this line.
+ }
+ System.err.println("Found expected lock for - \"" + threadCreator.getThreadNameToCheck() + "\"");
+ if( !blockingThreadName.equals(threadCreator.getOwnerName()) ){
+ System.err.println("Did not find expected owning thread \"" + threadCreator.getOwnerName() + "\"");
+ System.err.println("Found: \"" + blockingThreadName + "\"");
+ System.err.println("*** FAIL ***");
+ passed = false;
+ System.err.println("------------");
+ } else {
+ System.err.println("Confirmed " + blockingThreadName + " held the lock blocking " + blockedThreadName);
+ System.err.println("Pass");
+ lockCount++;
+ System.err.println("------------");
+ }
+ continue;
+ }
+ if( line.startsWith("java.util.concurrent locks in use")) {
+ break; // Done with monitors, juc locks next.
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading jdmpview output file.");
+ System.exit(1);
+ }
+ System.err.println("Checked " + lockCount + " blocked threads out of " + expectedLockCount + " expected blocked threads");
+ if( threadNameToCreator.size() != 0 ) {
+ passed = false;
+ System.err.println("Failed to find all expected threads blocked: ");
+ for( Object key: threadNameToCreator.keySet() ) {
+ System.err.println("Missing thread: \"" + key + "\"");
+ }
+ } else {
+ System.err.println("Found and checked all expected threads.");
+ }
+ return passed;
+ }
+
+ private static boolean checkThreadSection(BufferedReader in) {
+ String line;
+ // Increment this every time we find one of our threads.
+ int threadCount = 0;
+ boolean passed = true;
+ Map threadNameToCreator = new HashMap();
+
+ System.err.println("Checking Thread Blockers");
+
+ for(CoreThreadCreator job: CoreThreadCreator.setupJobs ) {
+ threadNameToCreator.put(job.getThreadNameToCheck(), job);
+ }
+ final int expectedThreadCount = threadNameToCreator.size();
+
+ try {
+ line = in.readLine();
+ while (line != null) {
+ if( !line.startsWith(THREADINFO_TAG)) {
+ // Skip boring lines.
+ line = in.readLine();
+ continue;
+ }
+ String threadName = getThreadNameFromThreadInfo(line);
+ CoreThreadCreator threadCreator = (CoreThreadCreator)threadNameToCreator.remove(threadName);
+ if( threadName == null || threadCreator == null ) {
+ line = in.readLine();
+ continue;
+ }
+ System.err.println("Found expected thread - \"" + threadCreator.getThreadNameToCheck() + "\"");
+ threadCount++;
+
+ // Skip to monitor line
+ while( (findMatchingStartTag(line, THREADBLOCK_TAGS) == null) && !line.startsWith(" Java stack frames:")) {
+ line = in.readLine();
+ }
+ if( (findMatchingStartTag(line, THREADBLOCK_TAGS) == null)) {
+ passed = false;
+ System.err.println("No blocking information line for thread " + threadName);
+ System.err.println("Fail");
+ System.err.println("------------");
+ // This isn't a blocked thread so carry on.
+ line = in.readLine();
+ continue;
+ }
+ System.err.println("Blocked line: " + line);
+ if( threadCreator.checkJdmpviewInfoThreadLine(line.substring(findMatchingStartTag(line, THREADBLOCK_TAGS).length() )) ) {
+ System.err.println("Pass");
+ } else {
+ System.err.println("*** FAIL ***");
+ passed = false;
+ }
+ System.err.println("------------");
+ line = in.readLine();
+ }
+ } catch (IOException e) {
+ System.err.println("Error reading javacore file.");
+ System.exit(1);
+ }
+ System.err.println("Checked " + threadCount + " threads out of " + expectedThreadCount + " expected threads");
+ if( threadNameToCreator.size() != 0 ) {
+ passed = false;
+ System.err.println("Failed to find all expected threads: ");
+ for( Object key: threadNameToCreator.keySet() ) {
+ System.err.println("Missing thread: \"" + key + "\"");
+ }
+ } else {
+ System.err.println("Found and checked all expected threads.");
+ }
+ return passed;
+ }
+
+ public static String getThreadNameFromThreadInfo(String threadInfoLine) {
+ // Pull the thread name out of a line that looks like:
+ // name: Deadlock Thread 2
+ return threadInfoLine.substring(THREADINFO_TAG.length() );
+ }
+
+ private static String findMatchingStartTag(String toCheck, String[] possibilities) {
+ for( String s: possibilities ) {
+ if( toCheck.startsWith(s) ) {
+ return s;
+ }
+ }
+ return null;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CoreThreadCreator.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CoreThreadCreator.java
new file mode 100644
index 00000000000..62d5fe3ed93
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CoreThreadCreator.java
@@ -0,0 +1,744 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_thread;
+
+import com.ibm.dump.tests.javacore_thread.CoreThreadCreator;
+
+import java.lang.Thread.State;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
+
+public abstract class CoreThreadCreator implements Runnable {
+
+ public static final CoreThreadCreator[] setupJobs = {
+ new CoreThreadCreator.BlockedOnSynchronized(), new CoreThreadCreator.BlockedOnJUCLock(),
+ new CoreThreadCreator.TimedBlockedOnJUCLock(), new CoreThreadCreator.DeadlockedOnJUCLock(),
+ new CoreThreadCreator.BlockedOnFIFOMutex(), new CoreThreadCreator.BlockedOnOwnableFIFOMutex(),
+ new CoreThreadCreator.ParkedThread(), new CoreThreadCreator.WaitingOnSynchronized(),
+ new CoreThreadCreator.WaitingOnUnowned() };
+
+ public abstract String getThreadNameToCheck();
+
+ public String getLockName() {
+ return "";
+ }
+
+ public String getOwnerName() {
+ return "";
+ }
+
+ // Default implementation
+ public boolean checkBlockingLine(String line) {
+
+ boolean good = true;
+ good &= line.contains("Parked on: " + getLockName());
+ // Threads are quoted, unknowns aren't.
+ good &= line.contains("Owned by: " + getOwnerName()) || line.contains("Owned by: \"" + getOwnerName() + "\"");
+ return good;
+ }
+
+ public boolean checkWaitingLine(String line) {
+
+ boolean good = true;
+ good &= line.contains("Parked on: " + getLockName());
+ // Threads are quoted, unknowns aren't.
+ good &= line.contains("Owned by: " + getOwnerName()) || line.contains("Owned by: \"" + getOwnerName() + "\"");
+ return good;
+ }
+
+ public boolean checkJdmpviewInfoThreadLine(String line) {
+
+ boolean good = true;
+ good &= line.contains(getLockName() + "@0x");
+ good &= line.contains("owner name: \"" + getOwnerName() + "\" owner id: ");
+ return good;
+ }
+
+ public abstract boolean isReady();
+
+ public static class ParkedThread extends CoreThreadCreator {
+
+ private Thread parkingThread = null;
+
+ public boolean isReady() {
+ if (parkingThread != null
+ && parkingThread.getState() == State.WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ parkingThread = Thread.currentThread();
+ parkingThread.setName(getThreadNameToCheck());
+ LockSupport.park();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "ParkedThread: parked thread";
+ }
+
+ public boolean checkJdmpviewInfoThreadLine(String line) {
+
+ boolean good = true;
+ good &= line.contains("");
+ return good;
+ }
+ }
+
+ public static class BlockedOnJUCLock extends CoreThreadCreator {
+
+ private final ReentrantLock jucLock = new ReentrantLock(true);
+
+ private Thread parkingThread = null;
+ private Thread blockingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (parkingThread != null
+ && parkingThread.getState() == State.WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ blockingThread = new Thread(new Runnable() {
+ public void run() {
+ jucLock.lock();
+ lockTaken = true;
+ while (true) {
+ try {
+ // Hold the lock forever, but don't terminate.
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ });
+ blockingThread.setName(getOwnerName());
+ blockingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ parkingThread = new Thread(new Runnable() {
+ public void run() {
+ jucLock.lock();
+ }
+ });
+ parkingThread.setName(getThreadNameToCheck());
+ parkingThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "BlockedOnJUCLock: waiting thread";
+ }
+
+ public String getLockName() {
+ return "java/util/concurrent/locks/ReentrantLock$FairSync";
+ }
+
+ public String getOwnerName() {
+ return "BlockedOnJUCLock: lock owner";
+ }
+ }
+
+ public static class TimedBlockedOnJUCLock extends CoreThreadCreator {
+
+ private final ReentrantLock jucLock = new ReentrantLock(true);
+
+ private Thread parkingThread = null;
+ private Thread blockingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (parkingThread != null
+ && parkingThread.getState() == State.TIMED_WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ blockingThread = new Thread(new Runnable() {
+ public void run() {
+ jucLock.lock();
+ lockTaken = true;
+ while (true) {
+ try {
+ // Hold the lock forever, but don't terminate.
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ });
+ blockingThread.setName("TimedBlockedOnJUCLock: lock owner");
+ blockingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ parkingThread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ // We want a thread that will be in a timed park,
+ // but without any risk of it actually waking up.
+ jucLock.tryLock(10, TimeUnit.DAYS);
+ } catch (InterruptedException e) {
+ }
+ }
+ });
+ parkingThread.setName(getThreadNameToCheck());
+ parkingThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "TimedBlockedOnJUCLock: waiting thread";
+ }
+
+ public String getLockName() {
+ return "java/util/concurrent/locks/ReentrantLock$FairSync";
+ }
+
+ public String getOwnerName() {
+ return "TimedBlockedOnJUCLock: lock owner";
+ }
+ }
+
+ public static class DeadlockedOnJUCLock extends CoreThreadCreator {
+
+ private final ReentrantLock jucLock = new ReentrantLock(true);
+
+ private Thread parkingThread = null;
+ private Thread setupThread = null;
+
+ public boolean isReady() {
+ if (setupThread != null
+ && setupThread.getState() == State.TERMINATED
+ && parkingThread != null
+ && parkingThread.getState() == State.WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ jucLock.lock();
+ setupThread = Thread.currentThread();
+ setupThread.setName(getOwnerName());
+ parkingThread = new Thread(new Runnable() {
+ public void run() {
+ jucLock.lock();
+ }
+ });
+ parkingThread.setName(getThreadNameToCheck());
+ parkingThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "DeadlockedOnJUCLock: waiting thread";
+ }
+
+ @Override
+ public String getLockName() {
+ return "java/util/concurrent/locks/ReentrantLock$FairSync";
+ }
+
+ @Override
+ public String getOwnerName() {
+ return "DeadlockedOnJUCLock: lock owner (dead)";
+ }
+
+ @Override
+ public boolean checkBlockingLine(String line) {
+ boolean good = super.checkBlockingLine(line);
+ // Make sure the J9VMThread for this case is null.
+ good &= line.contains("Owned by: \"" + getOwnerName()
+ + "\" (J9VMThread:, java/lang/Thread:");
+ return good;
+ }
+
+ @Override
+ public boolean checkJdmpviewInfoThreadLine(String line) {
+ boolean good = super.checkJdmpviewInfoThreadLine(line);
+ // Make sure the J9VMThread for this case is null.
+ good &= line.contains("owner name: \"" + getOwnerName() + "\" owner id: ");
+ return good;
+ }
+ }
+
+ public static class BlockedOnFIFOMutex extends CoreThreadCreator {
+
+ private final FIFOMutex fifoMutex = new FIFOMutex();
+
+ private Thread parkingThread = null;
+ private Thread blockingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (parkingThread != null
+ && parkingThread.getState() == State.WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ blockingThread = new Thread(new Runnable() {
+ public void run() {
+ fifoMutex.lock();
+ lockTaken = true;
+ // Hold the lock forever, but don't terminate.
+ while (true) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ });
+ blockingThread.setName(getOwnerName());
+ blockingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ parkingThread = new Thread(new Runnable() {
+ public void run() {
+ fifoMutex.lock();
+ }
+ });
+ parkingThread.setName(getThreadNameToCheck());
+ parkingThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "BlockedOnFIFOMutex: waiting thread";
+ }
+
+ @Override
+ public String getLockName() {
+ return fifoMutex.getClass().getName().replace('.', '/');
+ }
+
+ }
+
+ public static class BlockedOnOwnableFIFOMutex extends CoreThreadCreator {
+
+ private final OwnableFIFOMutex fifoMutex = new OwnableFIFOMutex();
+
+ private Thread parkingThread = null;
+ private Thread blockingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (parkingThread != null
+ && parkingThread.getState() == State.WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ blockingThread = new Thread(new Runnable() {
+ public void run() {
+ fifoMutex.lock();
+ lockTaken = true;
+ while (true) {
+ try {
+ // Hold the lock forever, but don't terminate.
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ });
+ blockingThread.setName(getOwnerName());
+ blockingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ parkingThread = new Thread(new Runnable() {
+ public void run() {
+ fifoMutex.lock();
+ }
+ });
+ parkingThread.setName(getThreadNameToCheck());
+ parkingThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "BlockedOnOwnableFIFOMutex: waiting thread";
+ }
+
+ @Override
+ public String getLockName() {
+ return fifoMutex.getClass().getName().replace('.', '/');
+ }
+
+ @Override
+ public String getOwnerName() {
+ return "BlockedOnOwnableFIFOMutex: lock owner";
+ }
+ }
+
+ public static class BlockedOnSynchronized extends CoreThreadCreator {
+
+ private final String lock = "Lock for BlockedOnSynchronized";
+
+ private Thread parkingThread = null;
+ private Thread blockingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (parkingThread != null
+ && parkingThread.getState() == State.BLOCKED) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isSynchronizedLock() {
+ return true;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ blockingThread = new Thread(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ lockTaken = true;
+ while (true) {
+ try {
+ // Hold the lock forever, but don't terminate.
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+ });
+ blockingThread.setName(getOwnerName());
+ blockingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ parkingThread = new Thread(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ }
+ }
+ });
+ parkingThread.setName(getThreadNameToCheck());
+ parkingThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "BlockedOnSynchronized: blocked thread";
+ }
+
+ @Override
+ public String getLockName() {
+ return lock.getClass().getName().replace('.', '/');
+ }
+
+ @Override
+ public String getOwnerName() {
+ return "BlockedOnSynchronized: lock owner";
+ }
+
+ public boolean checkBlockingLine(String line) {
+
+ boolean good = true;
+ good &= line.contains("Blocked on: " + getLockName());
+ // Threads are quoted, unknowns aren't.
+ good &= line.contains("Owned by: " + getOwnerName()) || line.contains("Owned by: \"" + getOwnerName() + "\"");
+ return good;
+ }
+ }
+
+ public static class WaitingOnSynchronized extends CoreThreadCreator {
+
+ private final String lock = "Lock for WaitingOnSynchronized";
+
+ private Thread owningThread = null;
+ private Thread waitingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (waitingThread != null
+ && waitingThread.getState() == State.WAITING
+ && owningThread != null
+ && owningThread.getState() == State.TIMED_WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isSynchronizedLock() {
+ return true;
+ }
+
+ public void run() {
+ // First thread will wait on the object lock
+ waitingThread = new Thread(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ lockTaken = true;
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ });
+ waitingThread.setName(getThreadNameToCheck());
+ waitingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ // Second thread will take and own the lock forever
+ owningThread = new Thread(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ while (true) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+ });
+ owningThread.setName(getOwnerName());
+ owningThread.start();
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "WaitingOnSynchronized: waiting thread";
+ }
+
+ @Override
+ public String getLockName() {
+ return lock.getClass().getName().replace('.', '/');
+ }
+
+ @Override
+ public String getOwnerName() {
+ return "WaitingOnSynchronized: lock owner";
+ }
+
+ public boolean checkBlockingLine(String line) {
+
+ boolean good = true;
+ good &= line.contains("Waiting on: " + getLockName());
+ // Threads are quoted, unknowns aren't.
+ good &= line.contains("Owned by: " + getOwnerName()) || line.contains("Owned by: \"" + getOwnerName() + "\"");
+ return good;
+ }
+
+ public boolean checkJdmpviewInfoThreadLine(String line) {
+
+ boolean good = true;
+ good &= line.contains(getLockName() + "@0x");
+ good &= line.contains("owner name: \"" + getOwnerName() + "\" owner id:");
+ return good;
+ }
+ }
+
+ public static class WaitingOnUnowned extends CoreThreadCreator {
+
+ private final String lock = "Lock for WaitingOnUnowned";
+
+ private Thread owningThread = null;
+ private Thread waitingThread = null;
+ private volatile boolean lockTaken = false;
+
+ public boolean isReady() {
+ if (waitingThread != null
+ && waitingThread.getState() == State.WAITING) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isSynchronizedLock() {
+ return true;
+ }
+
+ public void run() {
+ // Take the lock, thread will terminate without releasing
+ // leaving the second thread blocked.
+ waitingThread = new Thread(new Runnable() {
+ public void run() {
+ synchronized (lock) {
+ lockTaken = true;
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ });
+ waitingThread.setName(getThreadNameToCheck());
+ waitingThread.start();
+ while (!lockTaken) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ @Override
+ public String getThreadNameToCheck() {
+ return "WaitingOnUnowned: waiting thread";
+ }
+
+ @Override
+ public String getLockName() {
+ return lock.getClass().getName().replace('.', '/');
+ }
+
+ public String getOwnerName() {
+ return "";
+ }
+
+ public boolean checkBlockingLine(String line) {
+
+ boolean good = true;
+ good &= line.contains("Waiting on: " + getLockName());
+ // Threads are quoted, unknowns aren't.
+ good &= line.contains("Owned by: " + getOwnerName()) || line.contains("Owned by: \"" + getOwnerName() + "\"");
+ return good;
+ }
+
+ public boolean checkJdmpviewInfoThreadLine(String line) {
+
+ boolean good = true;
+ System.err.println("Checking: |" + line +"|");
+ good &= line.contains(getLockName() + "@0x");
+ good &= line.contains("owner name: " + getOwnerName());
+ return good;
+ }
+ }
+
+ public boolean isSynchronizedLock() {
+ return false;
+ }
+
+ public boolean isAbstractOwnableSynchronizer() {
+ return false;
+ }
+
+
+// public static class DeadlockCycleOnJUCLock extends CoreThreadCreator {
+//
+// private final ReentrantLock jucLockA = new ReentrantLock(true);
+// private final ReentrantLock jucLockB = new ReentrantLock(true);
+//
+// private Thread threadA = null;
+// private Thread threadB = null;
+//
+// public boolean isReady() {
+// if (jucLockA.isLocked() && jucLockB.isLocked() && threadB != null
+// && jucLockA.isLocked()
+// && threadA != null
+// && threadA.getState() == State.WAITING) {
+// return true;
+// }
+// return false;
+// }
+//
+// public void run() {
+// parkingThread = new Thread(new Runnable() {
+// public void run() {
+// jucLockB.lock();
+// jucLockA.lock();
+// }
+// });
+// parkingThread.setName(getThreadNameToCheck());
+// parkingThread.start();
+// }
+//
+// @Override
+// public String getThreadNameToCheck() {
+// return "DeadlockedOnJUCLock: waiting thread";
+// }
+//
+// @Override
+// public String getLockName() {
+// return "java/util/concurrent/locks/ReentrantLock$FairSync";
+// }
+//
+// @Override
+// public String getOwnerName() {
+// return "DeadlockedOnJUCLock: lock owner (dead)";
+// }
+//
+// @Override
+// public boolean checkBlockingLine(String line) {
+// boolean good = super.checkBlockingLine(line);
+// // Make sure the J9VMThread for this case is null.
+// good &= line.contains("Owned by: \"" + getOwnerName()
+// + "\" (J9VMThread:, java/lang/Thread:");
+// return good;
+// }
+// }
+}
\ No newline at end of file
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CreateJavaCore.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CreateJavaCore.java
new file mode 100644
index 00000000000..092f9375235
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/CreateJavaCore.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_thread;
+
+import java.lang.Thread.State;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class CreateJavaCore {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ boolean generateSystemCore = false;
+ if( args.length > 0 && args[0].equals("-core") ) {
+ // Only generate system core if that's what we're testing to save space.
+ // (We might as well always generate a javacore, they aren't big and would
+ // be useful for debugging problems with the core tests.)
+ generateSystemCore = true;
+ }
+ for(CoreThreadCreator job: CoreThreadCreator.setupJobs ) {
+ Thread t = new Thread(job);
+ t.setName("Setup for" + job.getClass().getName());
+ System.out.println("Running: " + t.getName());
+ t.start();
+ }
+ for(CoreThreadCreator job: CoreThreadCreator.setupJobs ) {
+ System.out.println("Checking: " + job + " is ready.");
+ while( !job.isReady() ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // Likely to just keep waiting. May have to
+ // add a timeout in case something goes wrong.
+ }
+ }
+ }
+ com.ibm.jvm.Dump.JavaDump();
+ if( generateSystemCore ) {
+ com.ibm.jvm.Dump.SystemDump();
+ }
+ // We've deliberately deadlocked a bunch of threads.
+ // Don't wait for them before quitting.
+ System.exit(0);
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/FIFOMutex.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/FIFOMutex.java
new file mode 100644
index 00000000000..871cbbd4dd7
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/FIFOMutex.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_thread;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * Example FIFOMutex from the JUC docs.
+ */
+class FIFOMutex {
+ private final AtomicBoolean locked = new AtomicBoolean(false);
+ private final Queue waiters
+ = new ConcurrentLinkedQueue();
+
+
+ public void lock() {
+ long i = 0;
+ boolean wasInterrupted = false;
+ Thread current = Thread.currentThread();
+ waiters.add(current);
+
+ // Block while not first in queue or cannot acquire lock
+ while (waiters.peek() != current ||
+ !locked.compareAndSet(false, true)) {
+ LockSupport.park(this);
+ i++;
+ if (Thread.interrupted()) {// ignore interrupts while waiting
+ wasInterrupted = true;
+ }
+ }
+
+ waiters.remove();
+ if (wasInterrupted) { // reassert interrupt status on exit
+ current.interrupt();
+ }
+ }
+
+ public void unlock() {
+ locked.set(false);
+ LockSupport.unpark(waiters.peek());
+ }
+ }
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/OwnableFIFOMutex.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/OwnableFIFOMutex.java
new file mode 100644
index 00000000000..27a7a441892
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/javacore_thread/OwnableFIFOMutex.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.javacore_thread;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.AbstractOwnableSynchronizer;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * Example FIFOMutex from the JUC docs.
+ * Altered to extend AbstractOwnableSynchronizer to
+ * confirm we can introspect user code that extends
+ * this not just default class library versions.
+ */
+class OwnableFIFOMutex extends AbstractOwnableSynchronizer{
+ private final AtomicBoolean locked = new AtomicBoolean(false);
+ private final Queue waiters
+ = new ConcurrentLinkedQueue();
+
+
+ public void lock() {
+ long i = 0;
+ boolean wasInterrupted = false;
+ Thread current = Thread.currentThread();
+ waiters.add(current);
+
+ // Block while not first in queue or cannot acquire lock
+ while (waiters.peek() != current ||
+ !locked.compareAndSet(false, true)) {
+ LockSupport.park(this);
+ i++;
+ if (Thread.interrupted()) {// ignore interrupts while waiting
+ wasInterrupted = true;
+ }
+ }
+
+ waiters.remove();
+ setExclusiveOwnerThread(current);
+ if (wasInterrupted) { // reassert interrupt status on exit
+ current.interrupt();
+ }
+ }
+
+ public void unlock() {
+ setExclusiveOwnerThread(null);
+ locked.set(false);
+ LockSupport.unpark(waiters.peek());
+ }
+ }
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/jdmpview_heapdump/CompareDumps.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/jdmpview_heapdump/CompareDumps.java
new file mode 100644
index 00000000000..ce65533d356
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/jdmpview_heapdump/CompareDumps.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.jdmpview_heapdump;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class CompareDumps {
+
+ public static void main(String[] args) throws IOException {
+
+ int error_count = 0;
+ if (args.length != 2) {
+ System.err.println("CreateDump takes two arguments: the names of two files to compare");
+ }
+
+ System.err.println("Comparing the first 1000 lines of " + args[0] + " with the first 1000 lines of " + args[1]);
+ BufferedReader in1 = new BufferedReader(new FileReader(args[0]));
+ BufferedReader in2 = new BufferedReader(new FileReader(args[1]));
+
+ for (int i = 0;i<1000;i++) {
+ String line1 = in1.readLine();
+ String line2 = in2.readLine();
+ if ( ! line1.equals(line2)) {
+ error_count++;
+ System.err.println("The two files differ at line " + (i + 1));
+ System.err.println("The first file has:");
+ System.err.println(line1);
+ System.err.println("The second file has:");
+ System.err.println(line2);
+ }
+ }
+
+ System.err.println("Count of differences in the first 1000 lines: " + error_count);
+
+ System.exit(error_count);
+}
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/jdmpview_heapdump/CreateDumps.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/jdmpview_heapdump/CreateDumps.java
new file mode 100644
index 00000000000..239481c51b3
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/jdmpview_heapdump/CreateDumps.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.jdmpview_heapdump;
+
+public class CreateDumps {
+
+ public static void main(String[] args) {
+ System.gc();
+ System.gc();
+ com.ibm.jvm.Dump.HeapDump();
+ com.ibm.jvm.Dump.SystemDump();
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/memorycategories/DTFJMemoryCategoryTest.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/memorycategories/DTFJMemoryCategoryTest.java
new file mode 100644
index 00000000000..61791b5e94c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/memorycategories/DTFJMemoryCategoryTest.java
@@ -0,0 +1,402 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.memorycategories;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import com.ibm.dtfj.image.CorruptDataException;
+import com.ibm.dtfj.image.DataUnavailable;
+import com.ibm.dtfj.image.Image;
+import com.ibm.dtfj.image.ImageAddressSpace;
+import com.ibm.dtfj.image.ImageProcess;
+import com.ibm.dtfj.java.JavaRuntime;
+import com.ibm.dtfj.java.JavaRuntimeMemoryCategory;
+
+/**
+ * Test class that will check all JavaRuntimes inside an Image
+ * and checks the state of the JavaRuntimeMemoryCategories.
+ *
+ * Encapsulates knowledge of which memory categories are expected to be present,
+ * and what constitutes sanity for a
+ *
+ * @author andhall
+ *
+ */
+public final class DTFJMemoryCategoryTest
+{
+ /* List of memory categories we expect to have in all good dumps with default options */
+ public static final List EXPECTED_MEMORY_CATEGORIES;
+
+ static {
+ List localList = new ArrayList();
+
+ localList.add("JRE");
+ localList.add("JRE/VM");
+ localList.add("JRE/VM/Classes");
+ localList.add("JRE/VM/Memory Manager (GC)");
+ localList.add("JRE/VM/Memory Manager (GC)/Java Heap");
+ localList.add("JRE/VM/Threads");
+ localList.add("JRE/VM/Threads/Java Stack");
+ localList.add("JRE/VM/Threads/Native Stack");
+ localList.add("JRE/VM/Port Library");
+ localList.add("JRE/Class Libraries");
+ /* Note: this test expects to be run against dumps from JIT-On VMs */
+ localList.add("JRE/JIT");
+ localList.add("JRE/JIT/JIT Code Cache");
+ localList.add("JRE/JIT/JIT Data Cache");
+
+ EXPECTED_MEMORY_CATEGORIES = Collections.unmodifiableList(localList);
+ }
+
+ private final Image image;
+ private final List failureReasons = new LinkedList();
+
+ public DTFJMemoryCategoryTest(Image image)
+ {
+ this.image = image;
+ }
+
+ /* Does the address space -> process -> Java runtime walk.
+ * We expect this test to be run on simple, good dumps. Any CorruptData is a test failure.
+ */
+ private void walkJavaRuntimes()
+ {
+ boolean javaRuntimeFound = false;
+ Iterator> addressSpaceIt = image.getAddressSpaces();
+
+ while (addressSpaceIt.hasNext()) {
+ Object addressSpaceObj = addressSpaceIt.next();
+
+ if (addressSpaceObj instanceof ImageAddressSpace) {
+ ImageAddressSpace addressSpace = (ImageAddressSpace) addressSpaceObj;
+
+ Iterator> processIt = addressSpace.getProcesses();
+
+ while( processIt.hasNext() ) {
+ Object processObj = processIt.next();
+
+ if (processObj instanceof ImageProcess) {
+ ImageProcess process = (ImageProcess) processObj;
+
+ Iterator> runtimeIt = process.getRuntimes();
+
+ while (runtimeIt.hasNext()) {
+ Object runtimeObj = runtimeIt.next();
+
+ if (runtimeObj instanceof JavaRuntime) {
+ JavaRuntime runtime = (JavaRuntime) runtimeObj;
+
+ testJavaRuntime(runtime);
+ javaRuntimeFound = true;
+ } else {
+ recordFailure("Corrupt JavaRuntime object : " + runtimeObj + ", type " + runtimeObj.getClass());
+ }
+ }
+
+ } else {
+ recordFailure("Corrupt ImageProcess object : " + processObj + ", type " + processObj.getClass());
+ }
+ }
+ } else {
+ recordFailure("Corrupt ImageAddressSpace object : " + addressSpaceObj + ", type " + addressSpaceObj.getClass());
+ }
+ }
+
+ if (! javaRuntimeFound) {
+ recordFailure("No JavaRuntime objects found in dump");
+ }
+ }
+
+ /**
+ * Test method run on each JavaRuntime found in the dump.
+ * @param runtime
+ */
+ private void testJavaRuntime(JavaRuntime runtime)
+ {
+ boolean sane = sanityCheckMemoryCategories(runtime);
+
+ if (sane) {
+ checkMemoryCategoryDetails(runtime);
+ } else {
+ recordFailure("MemoryCategory sanity check failed on runtime " + runtime + ". See other messages for details");
+ }
+ }
+
+ private void checkMemoryCategoryDetails(JavaRuntime runtime)
+ {
+ for (String path : EXPECTED_MEMORY_CATEGORIES) {
+ JavaRuntimeMemoryCategory category = findCategoryPath(runtime, path);
+
+ if (category == null) {
+ recordFailure("Dump missing expected memory category " + path);
+ }
+
+ /* None of the expected memory categories should have 0 counters */
+ try {
+ if (category.getDeepAllocations() <= 0) {
+ recordFailure("Expected memory category " + path + " has <=0 deepAllocations: " + category.getDeepAllocations());
+ }
+
+ if (category.getDeepBytes() <= 0) {
+ recordFailure("Expected memory category " + path + " has <=0 deepBytes: " + category.getDeepBytes());
+ }
+ } catch (CorruptDataException ex) {
+ recordFailure("CorruptDataException checking allocations/bytes from category " + path);
+ }
+ }
+ }
+
+ /**
+ * Finds a memory category based on a path
+ * @param runtime Java runtime to walk categories from
+ * @param path Qualified path to category e.g. JRE/Memory Manager (GC)/Java Heap
+ * @return JavaRuntimeMemoryCategory object, or null if not found
+ */
+ private JavaRuntimeMemoryCategory findCategoryPath(JavaRuntime runtime, String path)
+ {
+ // Strip any leading or trailing '/'
+ path = path.replaceAll("^/+", "");
+ path = path.replaceAll("/+$", "");
+
+ try {
+ return findCategoryPath(runtime.getMemoryCategories(), path);
+ } catch (DataUnavailable e) {
+ throw new Error("Unexpected DataUnavailable - this should have been caught in the sanity check");
+ }
+ }
+
+ private JavaRuntimeMemoryCategory findCategoryPath(Iterator> categoriesIt, String path)
+ {
+ int nextSeparatorIndex = path.indexOf('/');
+
+ String matchName = null;
+ if (nextSeparatorIndex != -1) {
+ matchName = path.substring(0, nextSeparatorIndex);
+ path = path.substring(nextSeparatorIndex + 1);
+ } else {
+ matchName = path;
+ path = "";
+ }
+
+ while (categoriesIt.hasNext()) {
+ Object categoryObj = categoriesIt.next();
+
+ if (categoryObj instanceof JavaRuntimeMemoryCategory) {
+ JavaRuntimeMemoryCategory category = (JavaRuntimeMemoryCategory) categoryObj;
+
+ try {
+ if (category.getName().equals(matchName)) {
+ if (path.length() == 0) {
+ return category;
+ } else {
+ return findCategoryPath(category.getChildren(), path);
+ }
+ }
+ } catch (CorruptDataException e) {
+ recordFailure("CorruptDataException getting name from category " + category, e);
+ }
+
+ } else {
+ /* Should have been caught in the sanity check */
+ throw new Error("Unexpected bad memory category object: " + categoryObj + " type: " + categoryObj.getClass() + " - this should have been caught in the sanity check");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Verifies that we can get memory categories from the runtime, and that
+ * there aren't any loops or repeated nodes.
+ */
+ private boolean sanityCheckMemoryCategories(JavaRuntime runtime)
+ {
+ try {
+ Iterator> memoryCategoryIt = runtime.getMemoryCategories();
+ boolean memoryCategoryFound = false;
+ Set knownSet = new HashSet();
+
+ while ( memoryCategoryIt.hasNext() ) {
+ Object memoryCategoryObj = memoryCategoryIt.next();
+
+ if (memoryCategoryObj instanceof JavaRuntimeMemoryCategory) {
+ JavaRuntimeMemoryCategory category = (JavaRuntimeMemoryCategory) memoryCategoryObj;
+ memoryCategoryFound = true;
+
+ if (! sanityWalkCategory(knownSet, category) ) {
+ return false;
+ }
+ } else {
+ recordFailure("Corrupt JavaRuntimeMemoryCategory returned from runtime " + runtime + "; Object = " + memoryCategoryObj + ", type = " + memoryCategoryObj.getClass());
+ }
+ }
+
+ if (! memoryCategoryFound) {
+ recordFailure("No memory categories iterated for runtime " + runtime);
+ return false;
+ }
+ return true;
+
+ } catch (DataUnavailable e) {
+ recordFailure("Runtime " + runtime + " has no memory categories available");
+ return false;
+ }
+ }
+
+ private boolean sanityWalkCategory(Set knownSet, JavaRuntimeMemoryCategory currentCategory)
+ {
+ String currentCategoryName;
+ try {
+ currentCategoryName = currentCategory.getName();
+ } catch (CorruptDataException e1) {
+ recordFailure("CorruptDataException trying to read name of category " + currentCategory, e1);
+ currentCategoryName = "";
+ }
+
+ if (knownSet.contains(currentCategory)) {
+ recordFailure("Loop detected in JavaRuntimeMemoryCategory tree. Found " + currentCategory + " at least twice. Name = " + currentCategoryName);
+ return false;
+ }
+
+ knownSet.add(currentCategory);
+
+ Iterator> childIt = null;
+ try {
+ childIt = currentCategory.getChildren();
+ } catch (CorruptDataException e) {
+ recordFailure("CorruptDataException trying to get children of category " + currentCategoryName, e);
+ //Even though we can't walk children - we haven't found a loop or any really dangerous damage
+ //so we'll call this sane
+ return true;
+ }
+
+ try {
+ long deepBytes = currentCategory.getDeepBytes();
+ if (deepBytes < 0) {
+ recordFailure("Category " + currentCategoryName + " has negative deepBytes: " + deepBytes);
+ return false;
+ }
+
+ long shallowBytes = currentCategory.getShallowBytes();
+ if (shallowBytes < 0) {
+ recordFailure("Category " + currentCategoryName + " has negative shallowBytes: " + shallowBytes);
+ return false;
+ }
+
+ long deepAllocations = currentCategory.getDeepAllocations();
+ if (deepAllocations < 0) {
+ recordFailure("Category " + currentCategoryName + " has negative deepAllocations: " + deepAllocations);
+ return false;
+ }
+
+ long shallowAllocations = currentCategory.getShallowAllocations();
+ if (shallowAllocations < 0) {
+ recordFailure("Category " + currentCategoryName + " has negative shallowAllocations: " + shallowAllocations);
+ return false;
+ }
+
+ } catch (CorruptDataException ex) {
+ recordFailure("CorruptDataException thrown trying to introspect category " + currentCategoryName, ex);
+ return false;
+ }
+
+ try {
+ currentCategory.getMemorySections(false);
+ currentCategory.getMemorySections(true);
+ } catch (CorruptDataException e) {
+ recordFailure("CorruptDataException thrown trying to getMemorySections from " + currentCategoryName, e);
+ return false;
+ } catch (DataUnavailable e) {
+ //This is permissable
+ }
+
+ while (childIt.hasNext()) {
+ Object childCategoryObj = childIt.next();
+
+ if (childCategoryObj instanceof JavaRuntimeMemoryCategory) {
+ JavaRuntimeMemoryCategory childCategory = (JavaRuntimeMemoryCategory) childCategoryObj;
+
+ if (! sanityWalkCategory(knownSet, childCategory) ) {
+ return false;
+ }
+ } else {
+ recordFailure("Unrecognised child category " + childCategoryObj + " type: " + childCategoryObj.getClass() + " returned as child of category " + currentCategoryName);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean runTest() {
+ resetFailureInfo();
+
+ try {
+ walkJavaRuntimes();
+ } catch (Throwable t) {
+ recordFailure("Throwable caught in runTest()", t);
+ }
+
+ return testPassed();
+ }
+
+ private void recordFailure(String message)
+ {
+ failureReasons.add(message);
+ }
+
+ private void recordFailure(String message, Throwable t)
+ {
+ StringWriter writer = new StringWriter();
+ PrintWriter pw = new PrintWriter(writer);
+
+ pw.println(message);
+ t.printStackTrace(pw);
+
+ failureReasons.add(writer.toString());
+ }
+
+ private boolean testPassed()
+ {
+ return failureReasons.size() == 0;
+ }
+
+ private void resetFailureInfo()
+ {
+ failureReasons.clear();
+ }
+
+ public void printFailures()
+ {
+ for (String failure : failureReasons) {
+ System.err.println("* " + failure);
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/memorycategories/ValidateMemoryCategories.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/memorycategories/ValidateMemoryCategories.java
new file mode 100644
index 00000000000..7dfab819fce
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/memorycategories/ValidateMemoryCategories.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.memorycategories;
+
+import java.io.File;
+import java.io.IOException;
+
+import com.ibm.dtfj.image.Image;
+import com.ibm.dtfj.image.ImageFactory;
+
+/**
+ * Test application that reads a DTFJ image and validates that the state of its
+ * JavaRuntimeMemoryCategories.
+ *
+ * It uses knowledge of the memory categories that should be present to check
+ * the memory categories are being calculated, stored and parsed correctly.
+ *
+ * Usage:
+ *
+ * java com.ibm.memorycategories.ValidateMemoryCategories
+ */
+public class ValidateMemoryCategories
+{
+
+
+ public static void main(String args[]) throws Exception
+ {
+ if (args.length < 2) {
+ System.err.println("Unexpected number of arguments. Got " + args.length);
+ usage();
+ return;
+ }
+
+ String imageFactoryClassName = args[0];
+ String dumpPath = args[1];
+
+ System.err.println("Loading DTFJ Image");
+
+ Image image = loadImage(imageFactoryClassName, dumpPath);
+
+ DTFJMemoryCategoryTest test = new DTFJMemoryCategoryTest(image);
+
+ boolean success = false;
+
+ try {
+ success = test.runTest();
+ } finally {
+ if (success) {
+ System.err.println("Test PASSED");
+ } else {
+ System.err.println("Test FAILED");
+ System.err.println("Failure reasons:");
+ test.printFailures();
+ }
+ }
+
+ }
+
+ private static Image loadImage(String imageFactoryClassName, String dumpPath) {
+ Class> clazz = null;
+ try {
+ clazz = Class.forName(imageFactoryClassName);
+ } catch (ClassNotFoundException e) {
+ System.err.println("Cannot load supplied ImageFactory class name: " + imageFactoryClassName);
+ System.exit(1);
+ }
+
+ if (! ImageFactory.class.isAssignableFrom(clazz)) {
+ System.err.println("Supplied class: " + clazz.getName() + " does not implement the ImageFactory interface");
+ }
+
+ ImageFactory factory = null;
+ try {
+ factory = (ImageFactory) clazz.newInstance();
+ } catch (Exception e) {
+ System.err.println("Couldn't instantiate image factory from class: " + clazz.getName());
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+
+ try {
+ return factory.getImage(new File(dumpPath));
+ } catch (IOException e) {
+ System.err.println("Error creating Image from ImageFactory");
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ //Can't get here
+ throw new Error("Control shouldn't reach here");
+ }
+
+ private static void usage()
+ {
+ System.err.println("Usage:");
+ System.err.println();
+ System.err.println("java " + ValidateMemoryCategories.class.getName() + " ");
+ }
+}
\ No newline at end of file
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/oomtest/OOMTest.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/oomtest/OOMTest.java
new file mode 100644
index 00000000000..a53b6a345b9
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/oomtest/OOMTest.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.oomtest;
+
+import java.util.Vector;
+
+/**
+ * This class uses up memory.
+ *
+ * @author rleigh
+ *
+ */
+public class OOMTest {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ Vector myLongs = new Vector();
+
+ for (long i=0; i
+ info class com/ibm/dump/tests/types/packed/PackedPrimitives
+ name = com/ibm/dump/tests/types/packed/PackedPrimitives
+
+ ID = 0xf020730 superID = 0xf010150
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 3
+ total size of instances on the heap: 80 bytes
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+
+ String[] validTotalSizes = {
+ "80", // 32 and 64cr
+ "104" // 64
+ };
+ String command = "info class com/ibm/dump/tests/types/packed/PackedPrimitives";
+
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("3", 4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedPrimitives".
+ * Check that the "This class is packed" line is present.
+ * Check that there are three instances.
+ * Check that there is one on-heap packed instance and that the memory on the heap is right.
+ * Check that there are two off-heap packed instances and that the memory on the heap is right.
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedPrimitives
+ heap #1 - name: Java heap
+
+ "com/ibm/dump/tests/types/packed/PackedPrimitives" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedPrimitives @ 0x2ef488d0
+ This is an on-heap packed object occupying 48 bytes on the heap
+
+ references:
+ 0x2ef488d0
+
+ com/ibm/dump/tests/types/packed/PackedPrimitives @ 0x2ef48900
+ This is an off-heap packed object occupying 16 bytes on the heap
+
+ references:
+
+
+ com/ibm/dump/tests/types/packed/PackedPrimitives @ 0x2ef48910
+ This is an off-heap packed object occupying 16 bytes on the heap
+
+ references:
+
+ references:
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "48", // on heap 32 and 64cr
+ "16", // off heap 32 and 64cr
+ "56", // on heap 64
+ "24" // off heap 64
+ };
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedPrimitives";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedPrimitives @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedPrimitives @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an off-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedPrimitives @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an off-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest2ArrayOfPackedPrimitivesChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest2ArrayOfPackedPrimitivesChecker.java
new file mode 100644
index 00000000000..358943b107c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest2ArrayOfPackedPrimitivesChecker.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest2ArrayOfPackedPrimitivesChecker {
+
+ /**
+ * Check through the output looking for the output from "info class [Lcom/ibm/dump/tests/types/packed/PackedPrimitives;".
+ * Check that the "This class is packed" line is present.
+ * Check that there are two instances.
+ * Check that the memory on the heap is right.
+ *
+ * The expected output is as follows:
+ *
+> info class [Lcom/ibm/dump/tests/types/packed/PackedPrimitives;
+name = [Lcom/ibm/dump/tests/types/packed/PackedPrimitives;
+
+ ID = 0xf0764f0 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 2
+ total size of instances on the heap: 112 bytes
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {
+ "352", // 32
+ "368", // 64cr
+ "384"}; // 64
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedPrimitives$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j [Lcom/ibm/dump/tests/types/packed/PackedPrimitives;".
+ *
+ * The expected output is as follows:
+ *
+x/j [Lcom/ibm/dump/tests/types/packed/PackedPrimitives;
+ heap #1 - name: Java heap
+
+ [Lcom/ibm/dump/tests/types/packed/PackedPrimitives; @ 0x2ef491c0
+ This is an on-heap packed object occupying 336 bytes on the heap
+ This is an array of size 10
+ references:
+ 0x2ef491c0
+ [Lcom/ibm/dump/tests/types/packed/PackedPrimitives; @ 0x2ef49310
+ This is a native packed object occupying 16 bytes on the heap
+ The native memory is allocated at
+ This is an array of size 10
+ references:
+ [blank line]
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "336", // on heap 32
+ "16", // off heap 32
+ "344", // on heap 64cr
+ "24", // off heap 64cr
+ "352", // on heap 64
+ "32"}; // off heap 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedPrimitives$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ // Check for two packed primitive arrays, one of which is on-heap and has one reference, the other has no references
+ boolean passed = true;
+ int refCount = 0;
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToReferencesLine(3);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToReferencesLine(3);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= (refCount == 1); // expect one reference found in total
+
+ if (!passed) {
+ System.err.println("PortableHeapdumpTest2ArrayOfPackedPrimitivesChecker failed");
+ }
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest3PackedMixedChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest3PackedMixedChecker.java
new file mode 100644
index 00000000000..ce3824fbe51
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest3PackedMixedChecker.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest3PackedMixedChecker {
+
+ /**
+ * Check through the output "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef".
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/PackedMixedOneRef
+name = com/ibm/dump/tests/types/packed/PackedMixedOneRef
+
+ ID = 0xf020708 superID = 0xf010150
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 1
+ total size of instances on the heap: 24 bytes
+
+
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {
+ "24", // 32 and 64cr
+ "40" // 64
+ };
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("1", 4); // number of instances 1
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+ return passed;
+
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef
+ heap #1 - name: Java heap
+
+ "com/ibm/dump/tests/types/packed/PackedMixedOneRef" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedMixedOneRef @ 0x2ef49360
+ This is an on-heap packed object occupying 24 bytes on the heap
+
+ references:
+ 0x2ef49360 0x2ef49378
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "24", // on heap 32 and 64cr
+ "40"}; // on heap 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedOneRef @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ System.err.println("Checking the first reference from the PackedMixedOneRef is to a com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(2, 2);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+ return passed;
+
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest4ArrayOfPackedMixedOneRefChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest4ArrayOfPackedMixedOneRefChecker.java
new file mode 100644
index 00000000000..8c63c2348e0
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest4ArrayOfPackedMixedOneRefChecker.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest4ArrayOfPackedMixedOneRefChecker {
+
+ /**
+ * Check through the output looking for the output from "info class [Lcom/ibm/dump/tests/types/packed/PackedMixedOneRef;".
+ *
+ * The expected output is as follows:
+ *
+> info class [Lcom/ibm/dump/tests/types/packed/PackedMixedOneRef;
+name = [Lcom/ibm/dump/tests/types/packed/PackedMixedOneRef;
+
+ ID = 0xf0767f8 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 1
+ total size of instances on the heap: 56 bytes
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {
+ "96", // 32
+ "104", // 64cr
+ "192"}; // 64
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("1",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j [Lcom/ibm/dump/tests/types/packed/PackedMixedOneRef;".
+ *
+ * The essential point is that in the array we will see the references, not to the PackedMixedOneRef objects as we would if this were
+ * a normal array, but the references to the objects to which the PackedMixedOneRef objects point.
+ * The expected output is as follows:
+ *
+x/j [Lcom/ibm/dump/tests/types/packed/PackedMixedOneRef;
+ heap #1 - name: Java heap
+
+ [Lcom/ibm/dump/tests/types/packed/PackedMixedOneRef; @ 0x2ef493b8
+ This is an on-heap packed object occupying 96 bytes on the heap
+ This is an array of size 10
+ references:
+ 0x2ef49418 0x2ef49448 0x2ef49478 0x2ef494a8 0x2ef494d8 0x2ef49508 0x2ef49538 0x2ef49568 0x2ef49598 0x2ef495c8 0x2ef493b8
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "96", // on heap 32
+ "104", // on heap 64cr
+ "192" // on heap 64
+ };
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ System.err.println("Checking the first reference from the array of PackedMixedOneRef is to a com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(12, 11);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.java
new file mode 100644
index 00000000000..e927f9ed5c1
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest5ArrayOfPackedMixedTwoRefsChecker {
+
+
+
+ /**
+ * Check through the output looking for the output from "x/j [Lcom/ibm/dump/tests/types/packed/PackedMixedTwoRefs;".
+ *
+ * The essential point is that in the array we will see the references, not to the PackedMixedTwoRefs objects
+ * as we would if this were a normal array, but the references to the objects to which the PackedMixed objects point.
+ * Hence we expect to see 20 references, not 10.
+ *
+x/j [Lcom/ibm/dump/tests/types/packed/PackedMixedTwoRefs;
+ heap #1 - name: Java heap
+
+ [Lcom/ibm/dump/tests/types/packed/PackedMixedTwoRefs; @ 0x2ef49608
+ This is an on-heap packed object occupying 136 bytes on the heap
+ This is an array of size 10
+ references:
+ 0x2ef496c0 0x2ef49690 0x2ef49720 0x2ef496f0 0x2ef49780 0x2ef49750 0x2ef497e0 0x2ef497b0 0x2ef49840 0x2ef49810 0x2ef498a0 0x2ef49870 0x2ef49900 0x2ef498d0 0x2ef49960 0x2ef49930 0x2ef499c0 0x2ef49990 0x2ef49a20 0x2ef499f0 0x2ef49608
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "136", // on heap 32
+ "144", // 64cr
+ "272" // 64
+ };
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedTwoRefs$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedTwoRefs$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ System.err.println("Checking that the first reference from the array of PackedMixedTwoRefs is to an instance of com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(2, 21);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest6PackedMixedWithReferenceToSelfChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest6PackedMixedWithReferenceToSelfChecker.java
new file mode 100644
index 00000000000..8c99a3e5afb
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest6PackedMixedWithReferenceToSelfChecker.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest6PackedMixedWithReferenceToSelfChecker {
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf
+ heap #1 - name: Java heap
+
+ "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf @ 0x2ef49a50
+ This is an on-heap packed object occupying 24 bytes on the heap
+
+ references:
+ 0x2ef49a50 0x2ef49a50
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "24", // 32 and 64cr
+ "40"}; // 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+
+ System.err.println("Checking that the first (and only) reference from the PackedMixedWithReferenceToSelf is indeed to itself");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(8, 2);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf");
+
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest7NestedPackedChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest7NestedPackedChecker.java
new file mode 100644
index 00000000000..0333805661f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest7NestedPackedChecker.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest7NestedPackedChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/NestedPacked".
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/NestedPacked
+name = com/ibm/dump/tests/types/packed/NestedPacked
+
+ ID = 0xf077a80 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 2
+ total size of instances on the heap: 40 bytes
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {
+ "40", // 32
+ "48", // 64cr
+ "64"}; // 64
+
+
+ boolean passed = true;
+
+ String command = "info class com/ibm/dump/tests/types/packed/NestedPacked";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/NestedPacked".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/NestedPacked
+ heap #1 - name: Java heap
+
+ "com/ibm/dump/tests/types/packed/NestedPacked" has no static fields
+
+ com/ibm/dump/tests/types/packed/NestedPacked @ 0x2ef49a88
+ This is an on-heap packed object occupying 24 bytes on the heap
+
+ references:
+ 0x2ef49a88
+ com/ibm/dump/tests/types/packed/NestedPacked @ 0x2ef49aa0
+ This is a native packed object occupying 16 bytes on the heap
+ The native memory is allocated at
+
+ references:
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "24", // on heap 32
+ "16", // off heap 32
+ "32", // on heap 64cr
+ "16", // off heap 64cr
+ "40", // on heap 64
+ "24" // off heap 64
+ };
+
+ String command = "x/j com/ibm/dump/tests/types/packed/NestedPacked";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(2, 1);
+
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/NestedPacked @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an off-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(2, 0);
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest8PackedIntsArrayChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest8PackedIntsArrayChecker.java
new file mode 100644
index 00000000000..2e93bfe1269
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest8PackedIntsArrayChecker.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest8PackedIntsArrayChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/PackedIntsArray".
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/PackedIntsArray
+name = com/ibm/dump/tests/types/packed/PackedIntsArray
+
+ ID = 0xf076cf0 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 2
+ total size of instances on the heap: 56 bytes
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {
+ "56", // 32
+ "64", // 64cr
+ "80"}; // 64
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedIntsArray";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2", 4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedIntsArray".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedIntsArray
+ heap #1 - name: Java heap
+
+ "com/ibm/dump/tests/types/packed/PackedIntsArray" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedIntsArray @ 0x2ef49ca8
+ This is an on-heap packed object occupying 40 bytes on the heap
+
+ references:
+ 0x2ef49ca8
+ com/ibm/dump/tests/types/packed/PackedIntsArray @ 0x2ef49cd0
+ This is a native packed object occupying 16 bytes on the heap
+ The native memory is allocated at
+
+ references:
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {
+ "40", // on heap 32
+ "16", // off heap 32
+ "48", // on heap 64cr
+ "16", // off heap 64cr
+ "56", // on heap 64
+ "24" // off heap 64
+ };
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedIntsArray";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedIntsArray @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedIntsArray @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an off-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.java
new file mode 100644
index 00000000000..3b676bc02af
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/portable_heapdump_packed_objects/PortableHeapdumpTest9ArrayOfPackedMixedArrayElementChecker.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.portable_heapdump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class PortableHeapdumpTest9ArrayOfPackedMixedArrayElementChecker {
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedArrayElement".
+ *
+ * The essential point of this test is to check that the array has a reference to the packed object
+ * and that the derived object has a reference to the array
+ *
+ * The expected output is as follows:
+ *
+x/j [Lcom/ibm/dump/tests/types/packed/PackedMixedArrayElement;
+ heap #1 - name: Java heap
+
+ [Lcom/ibm/dump/tests/types/packed/PackedMixedArrayElement; @ 0x2ef49cf0
+ This is an on-heap packed object occupying 24 bytes on the heap
+ This is an array of size 1
+ references:
+ 0x2ef49d08 0x2ef49cf0
+x/j com/ibm/dump/tests/types/packed/PackedMixedArrayElement
+ heap #1 - name: Java heap
+
+ "com/ibm/dump/tests/types/packed/PackedMixedArrayElement" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedMixedArrayElement @ 0x2ef49a50
+ This is an on-heap packed object occupying 24 bytes on the heap
+
+ references:
+ 0x2ef49a50 0x2ef49a50
+ com/ibm/dump/tests/types/packed/PackedMixedArrayElement @ 0x2ef49d08
+ This is an on-heap packed object occupying 16 bytes on the heap
+
+ references:
+ 0x2ef49cf0
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validArraySizes = {
+ "24", // 32
+ "32", // 64cr
+ "40", // 64 nocr Z
+ "48"}; // 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validArraySizes,8);
+
+ System.err.println("Checking that the second reference from the array of PackedMixedArrayElement is to the element");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(2, 2);
+ String secondReference = o.getSecondReference();
+
+ // check the array points to the element
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedArrayElement");
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedArrayElement @ " + secondReference);
+
+ System.err.println("Checking that the first (and only) reference from the first element of the array of PackedMixedArrayElement is back to the array");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(5, 1);
+ String firstReference = o.getFirstReference();
+
+ // check the element points to the array
+ passed &= OutputFile.checkReferenceIsToObject(fileName, firstReference, "com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array");
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/CheckSystemDump.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/CheckSystemDump.java
new file mode 100644
index 00000000000..d3eab0e0855
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/CheckSystemDump.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * This class checks the output from jdmpview run against a PHD containing packed objects
+ *
+ * @author matthew
+ *
+ */
+public class CheckSystemDump {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.err.println("A file containing jdmpview output is required to check.");
+ System.exit(1);
+ }
+ String fileName = args[0];
+
+ System.err.println("Portable Heapdump Checker");
+ System.err.println("Checking " + fileName);
+
+ boolean passed = true;
+
+ try {
+ /**
+ * Test 1. Check PackedPrimitives
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 1. Check PackedPrimitives\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest1PackedPrimitivesChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest1PackedPrimitivesChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 2. Check array of PackedPrimitives
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 2. Check array of PackedPrimitives\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest2ArrayOfPackedPrimitivesChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest2ArrayOfPackedPrimitivesChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 3. Check PackedMixed
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 3. Check PackedMixedOneRef\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest3PackedMixedOneRefChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest3PackedMixedOneRefChecker.checkXJClassCommand(fileName);
+
+
+ /**
+ * Test 4. Check array of PackedMixed
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 4. Check array of PackedMixed\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest4ArrayOfPackedMixedOneRefChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest4ArrayOfPackedMixedOneRefChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 5. Check array of PackedMixedTwoRefs
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 5. Check PackedMixedTwoRefs\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest5ArrayOfPackedMixedTwoRefsChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 6. Check PackedMixedWithReferenceToSelf
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 6. Check PackedMixedWithReferenceToSelf\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest6PackedMixedWithReferenceToSelfChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 7. Check NestedPacked
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 7. Check NestedPacked and NestedPacked1\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest7NestedPackedChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest7NestedPackedChecker.checkXJClassCommand(fileName);
+ passed &= SystemDumpTest71NestedPacked1Checker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 8. Check NestedPackedMixed
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 8. Check NestedPackedMixed\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest8NestedPackedMixedChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest8NestedPackedMixedChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 9. Check PackedIntsArray
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 9. Check PackedIntsArray\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest9PackedIntsArrayChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest9PackedIntsArrayChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 10. Check PackedIntsArrayArray and derived object
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 10. Check PackedIntsArrayArray and derived object\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest10PackedIntsArrayArrayChecker.checkInfoClassCommand(fileName);
+ passed &= SystemDumpTest10PackedIntsArrayArrayChecker.checkXJClassCommand(fileName);
+ passed &= SystemDumpTest101DerivedPackedIntsArrayArrayChecker.checkXJClassCommand(fileName);
+
+ /**
+ * Test 11. Check array of PackedMixedWithReferenceToSelf
+ */
+ System.err.println("\n**************************************************\n");
+ System.err.println("* 11. Check array of PackedMixedWithReferenceToSelf\n");
+ System.err.println("**************************************************");
+ passed &= SystemDumpTest11ArrayOfPackedMixedArrayElementChecker.checkXJClassCommand(fileName);
+
+ } catch (FileNotFoundException e) {
+ System.err.println("FileNotFoundException occured reading " + fileName);
+ e.printStackTrace(System.err);
+ System.exit(1);
+ } catch (IOException e) {
+ System.err.println("IOException occured reading " + fileName);
+ e.printStackTrace(System.err);
+ System.exit(1);
+ }
+
+
+ if( passed ) {
+ System.err.println("Test passed.");
+ System.exit(0);
+ } else {
+ System.err.println("Test failed.");
+ System.exit(1);
+ }
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest101DerivedPackedIntsArrayArrayChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest101DerivedPackedIntsArrayArrayChecker.java
new file mode 100644
index 00000000000..092214fc63c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest101DerivedPackedIntsArrayArrayChecker.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest101DerivedPackedIntsArrayArrayChecker {
+
+ /**
+ * Check through the output looking for the output from "x/j [Lcom/ibm/dump/tests/types/packed/PackedIntsArray;".
+ *
+ * The expected output is as follows:
+ *
+> x/j [Lcom/ibm/dump/tests/types/packed/PackedIntsArray;
+ heap #1 - name: Generational@2d22b0
+
+ [Lcom/ibm/dump/tests/types/packed/PackedIntsArray; @ 0x2ef48e58
+ This is an on-heap packed object occupying 16 bytes on the heap
+ This is a derived packed object:
+ target object: com/ibm/dump/tests/types/packed/PackedIntsArrayArray @ 0x2ef48df8
+ target offset: 0xc
+ showing fields for [Lcom/ibm/dump/tests/types/packed/PackedIntsArray; packed @ 0x2ef48e04
+ 0: com/ibm/dump/tests/types/packed/PackedIntsArray packed @ 0x2ef48e04
+ 1: com/ibm/dump/tests/types/packed/PackedIntsArray packed @ 0x2ef48e20
+ 2: com/ibm/dump/tests/types/packed/PackedIntsArray packed @ 0x2ef48e3c
+
+ references:
+ 0x2ef48df8
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"16","24", "32"}; // object header on 32 , 64, 64 nocr
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedIntsArray$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(7, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(1, "This is a derived packed object");
+ passed &= o.skipLimitedToLineContaining(1, "target object: com/ibm/dump/tests/types/packed/PackedIntsArrayArray @ 0x");
+ passed &= o.skipLimitedToLineContaining(1, "target offset: 0x");
+ passed &= o.skipLimitedToLineContaining(1, "showing fields for com/ibm/dump/tests/types/packed/PackedIntsArray$Array packed @ 0x");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(6, 1);
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest10PackedIntsArrayArrayChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest10PackedIntsArrayArrayChecker.java
new file mode 100644
index 00000000000..b3dbe5dabd2
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest10PackedIntsArrayArrayChecker.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest10PackedIntsArrayArrayChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/PackedIntsArray".
+ *
+ * The expected output is as follows:
+ *
+info class com/ibm/dump/tests/types/packed/PackedIntsArrayArray
+name = com/ibm/dump/tests/types/packed/PackedIntsArrayArray
+
+ ID = 0x3f96c00 superID = 0x3cc2700
+ classLoader = 0x2ef39e78 modifiers: public final
+
+ This is a packed class
+
+ number of instances: 1
+ total size of instances on the heap: 96 bytes
+
+Inheritance chain....
+
+ com/ibm/jvm/packed/PackedObject
+ com/ibm/dump/tests/types/packed/PackedIntsArrayArray
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"96","192", "104", "112", "136"}; // 96 is 32bit, 136 is 64nocr, not sure about the others and can't run packed and compressed refs anyway
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedIntsArrayArray";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2", 4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedIntsArray".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedIntsArrayArray
+ heap #1 - name: Generational@83d0f8
+
+ "com/ibm/dump/tests/types/packed/PackedIntsArrayArray" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedIntsArrayArray @ 0x2ef49758
+ This is an on-heap packed object occupying 96 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ @Length(3) public com.ibm.dump.tests.types.packed.PackedIntsArray[] piArrayArray1 = com/ibm/dump/tests/types/packed/PackedIntsArray[3] packed @ 0x2ef49764
+
+ references:
+ 0x2ef49758
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"96","192", "104", "112", "32"}; // 32 , 64, nocr
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedIntsArrayArray";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedIntsArrayArray @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(3, "@Length(3) public com.ibm.dump.tests.types.packed.PackedIntsArray$Array piArrayArray1 = com/ibm/dump/tests/types/packed/PackedIntsArray$Array[3] packed @ 0x");
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest11ArrayOfPackedMixedArrayElementChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest11ArrayOfPackedMixedArrayElementChecker.java
new file mode 100644
index 00000000000..05cc836047c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest11ArrayOfPackedMixedArrayElementChecker.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest11ArrayOfPackedMixedArrayElementChecker {
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedArrayElement".
+ *
+ * The essential point of this test is to check that there is one reference and one only. This will be a
+ * reference to the one element in the array. The odd extra self-reference that
+ * all on-heap packed objects have will have been suppressed
+ *
+ * The expected output is as follows:
+ *
+x/j [Lcom/ibm/dump/tests/types/packed/PackedMixedArrayElement;
+ heap #1 - name: Generational@3960f0
+
+ [Lcom/ibm/dump/tests/types/packed/PackedMixedArrayElement; @ 0x2ef48b98
+ This is an on-heap packed object occupying 24 bytes on the heap
+ 0: com/ibm/dump/tests/types/packed/PackedMixedArrayElement packed @ 0x2ef48ba8
+
+ references:
+ 0x2ef48b98 0x2ef48bb0
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validArraySizes = {"24", "32", "40", "48"}; // on-heap 32, on-heap 64, 64 nocr Z, nocr
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedArrayElement$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validArraySizes,8);
+ passed &= o.skipLimitedToLineContaining(1, "0: com/ibm/dump/tests/types/packed/PackedMixedArrayElement packed @ 0x");
+
+ System.err.println("Checking that the second reference from the array of PackedMixedArrayElement is to the element");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(2, 2);
+ String secondReference = o.getSecondReference();
+
+ // check the second reference is to the element
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedArrayElement");
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest1PackedPrimitivesChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest1PackedPrimitivesChecker.java
new file mode 100644
index 00000000000..dcd4bd28f00
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest1PackedPrimitivesChecker.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest1PackedPrimitivesChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/PackedPrimitives".
+ * Check that the "This class is packed" line is present.
+ * Check that there are three instances.
+ * Check that there is one packed instance and that the memory on the heap is right.
+ * Check that there are two off-heap packed instances and that the memory on the heap is right.
+ *
+ * The expected output is as follows:
+ *
+ info class com/ibm/dump/tests/types/packed/PackedPrimitives
+ name = com/ibm/dump/tests/types/packed/PackedPrimitives
+
+ ID = 0xf020730 superID = 0xf010150
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 3
+ total size of instances on the heap: 80 bytes
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+
+ String[] validTotalSizes = {"80","120", "104"}; // 32 , 64, nocr
+ String command = "info class com/ibm/dump/tests/types/packed/PackedPrimitives";
+
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("3", 4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedPrimitives".
+ * Check that the "This class is packed" line is present.
+ * Check that there are three instances.
+ * Check that there is one packed instance and that the memory on the heap is right.
+ * Check that there are two off-heap packed instances and that the memory on the heap is right.
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedPrimitives
+ heap #1 - name: Generational@689b98
+
+ static fields for "com/ibm/dump/tests/types/packed/PackedPrimitives"
+ public static int staticIntField = 99 (0x63)
+ public static long staticLongField = 101 (0x65)
+
+ com/ibm/dump/tests/types/packed/PackedPrimitives @ 0x2ef49f38
+ This is an on-heap packed object occupying 48 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public byte byteField = 97 (0x61)
+ public boolean booleanField = true
+ public char charField = '\377' (0xff)
+ public int intField = 99 (0x63)
+ public float floatField = 123.4 (0x42f6cccd)
+ public double doubleField = 123.4 (0x405ed9999999999a)
+ public long longField = 101 (0x65)
+ public int int2Field = 98 (0x62)
+
+ references:
+ 0x2ef49f38
+
+ com/ibm/dump/tests/types/packed/PackedPrimitives @ 0x2ef49f68
+ This is an off-heap packed object occupying 16 bytes on the heap
+ The native memory is allocated at 0x68a118
+ The packed data is 32 bytes long
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public byte byteField = 97 (0x61)
+ public boolean booleanField = true
+ public char charField = '\377' (0xff)
+ public int intField = 99 (0x63)
+ public float floatField = 123.4 (0x42f6cccd)
+ public double doubleField = 123.4 (0x405ed9999999999a)
+ public long longField = 101 (0x65)
+ public int int2Field = 98 (0x62)
+
+ references:
+
+
+ com/ibm/dump/tests/types/packed/PackedPrimitives @ 0x2ef49f78
+ This is an off-heap packed object occupying 16 bytes on the heap
+ The native memory is allocated at 0x1000
+ The packed data is 32 bytes long
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public byte byteField =
+ public boolean booleanField =
+ public char charField =
+ public int intField =
+ public float floatField =
+ public double doubleField =
+ public long longField =
+ public int int2Field =
+
+ references:
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"48","16","56","24"}; // on-heap 32, off-heap 32, on-heap 64, off-heap 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedPrimitives";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(8, "public int intField");
+
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(8, "public int intField");
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(8, "public int intField");
+
+ return passed;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest2ArrayOfPackedPrimitivesChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest2ArrayOfPackedPrimitivesChecker.java
new file mode 100644
index 00000000000..a8215c3c81c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest2ArrayOfPackedPrimitivesChecker.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest2ArrayOfPackedPrimitivesChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/PackedPrimitives;".
+ * Check that the "This class is packed" line is present.
+ * Check that there are two instances.
+ * Check that the memory on the heap is right.
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/PackedPrimitives;
+name = com/ibm/dump/tests/types/packed/PackedPrimitives;
+
+ ID = 0xf0764f0 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 2
+ total size of instances on the heap: 112 bytes
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"352","384", "368"}; // 32, 64
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedPrimitives$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedPrimitives;".
+ *
+ * The expected output is as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"336","16","352","32", "344", "24"}; // on-heap 32, off-heap 32, on-heap 64, off-heap 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedPrimitives$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ // Check for two packed primitive arrays, one of which is on-heap and has one reference, the other has no references
+ boolean passed = true;
+ int refCount = 0;
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToReferencesLine(14);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedPrimitives$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToReferencesLine(14);
+ refCount += o.skipToNextLineAndCountReferences();
+
+ passed &= (refCount == 1); // expect one reference found in total
+
+ if (!passed) {
+ System.err.println("SystemDumpTest2ArrayOfPackedPrimitivesChecker failed");
+ }
+
+ return passed;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest3PackedMixedOneRefChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest3PackedMixedOneRefChecker.java
new file mode 100644
index 00000000000..b3e11c08af5
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest3PackedMixedOneRefChecker.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest3PackedMixedOneRefChecker {
+
+ /**
+ * Check through the output "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef".
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/PackedMixedOneRef
+name = com/ibm/dump/tests/types/packed/PackedMixedOneRef
+
+ ID = 0xf020708 superID = 0xf010150
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 1
+ total size of instances on the heap: 24 bytes
+
+
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"24","40"}; // 32 , 64
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("1", 4); // number of instances 1
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+ return passed;
+
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef
+ heap #1 - name: Generational@298c90
+
+ "com/ibm/dump/tests/types/packed/PackedMixedOneRef" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedMixedOneRef @ 0x2ef47f30
+ This is an on-heap packed object occupying 24 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 99 (0x63)
+ public com.ibm.dump.tests.types.notpacked.NotPackedPrimitives npp =
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"24","40"}; // 32 , 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedOneRef @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ System.err.println("Checking the second reference from the PackedMixedOneRef is to a com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(6, 2);
+ String secondReference = o.getSecondReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/notpacked/NotPackedPrimitives");
+ return passed;
+
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest4ArrayOfPackedMixedOneRefChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest4ArrayOfPackedMixedOneRefChecker.java
new file mode 100644
index 00000000000..da0c6ab4285
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest4ArrayOfPackedMixedOneRefChecker.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest4ArrayOfPackedMixedOneRefChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef;".
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/PackedMixed;
+name = com/ibm/dump/tests/types/packed/PackedMixed;
+
+ ID = 0xf0767f8 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 1
+ total size of instances on the heap: 56 bytes
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"96","192", "104"}; // 32 , 64
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("1",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixed;".
+ *
+ * The expected output is as follows:
+ *
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"96","192", "104"}; // 32 , 64
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ System.err.println("Checking the array contents show packed objects");
+ passed &= o.skipLimitedToLineContaining(1, "0: com/ibm/dump/tests/types/packed/PackedMixedOneRef packed @ ");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(12, 11);
+ String firstReference = o.getFirstReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, firstReference, "com/ibm/dump/tests/types/packed/PackedMixedOneRef$Array");
+
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest5ArrayOfPackedMixedTwoRefsChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest5ArrayOfPackedMixedTwoRefsChecker.java
new file mode 100644
index 00000000000..f3cce41ddab
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest5ArrayOfPackedMixedTwoRefsChecker.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest5ArrayOfPackedMixedTwoRefsChecker {
+
+
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedTwoRefs;".
+ *
+ *
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"136","272", "144"}; // 32 , 64
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedTwoRefs$Array";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedTwoRefs$Array @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+ System.err.println("Checking the array contents show packed objects");
+ passed &= o.skipLimitedToLineContaining(1, "0: com/ibm/dump/tests/types/packed/PackedMixedTwoRefs packed @ ");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(12, 21);
+ String firstReference = o.getFirstReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, firstReference, "com/ibm/dump/tests/types/packed/PackedMixedTwoRefs$Array");
+
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest6PackedMixedWithReferenceToSelfChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest6PackedMixedWithReferenceToSelfChecker.java
new file mode 100644
index 00000000000..ec8bced42ed
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest6PackedMixedWithReferenceToSelfChecker.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest6PackedMixedWithReferenceToSelfChecker {
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf".
+ *
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf
+ heap #1 - name: Generational@308c90
+
+ static fields for "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf"
+ public static int staticIntField = 99 (0x63)
+
+ com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf @ 0x2ef485d0
+ This is an on-heap packed object occupying 24 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 99 (0x63)
+ public com.ibm.jvm.packed.PackedObject obj =
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"24","40"}; // on-heap 32, on-heap 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipUnlimitedToLineContaining("com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+
+
+ System.err.println("Checking that the both references from the PackedMixedWithReferenceToSelf is indeed to itself");
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(8, 2);
+ String firstReference = o.getFirstReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, firstReference, "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf");
+
+ String secondReference = o.getFirstReference();
+
+ passed &= OutputFile.checkReferenceIsToObject(fileName, secondReference, "com/ibm/dump/tests/types/packed/PackedMixedWithReferenceToSelf");
+
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest71NestedPacked1Checker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest71NestedPacked1Checker.java
new file mode 100644
index 00000000000..17fa44a07fb
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest71NestedPacked1Checker.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest71NestedPacked1Checker {
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/NestedPacked1".
+ *
+ * We specifically want to find the derived object
+ * The expected output is as follows:
+ *
+ * BUT can appear in either order :-(
+ *
+ *
+x/j com/ibm/dump/tests/types/packed/NestedPacked1
+ heap #1 - name: Generational@709b98
+
+ static fields for "com/ibm/dump/tests/types/packed/NestedPacked1"
+ public static int staticIntField = 98 (0x62)
+
+ com/ibm/dump/tests/types/packed/NestedPacked1 @ 0x2ef4a7e0
+ This is an on-heap packed object occupying 16 bytes on the heap
+ This is a derived packed object:
+ target object: com/ibm/dump/tests/types/packed/NestedPacked @ 0x2ef4a7c8
+ target offset: 0x10
+ showing fields for com/ibm/dump/tests/types/packed/NestedPacked1 packed @ 0x2ef4a7d8
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 98 (0x62)
+ public com.ibm.dump.tests.types.packed.NestedPacked2 nestedPacked2Field = com/ibm/dump/tests/types/packed/NestedPacked2 packed @ 0x2ef4a7dc
+
+ references:
+ 0x2ef4a7c8
+
+ com/ibm/dump/tests/types/packed/NestedPacked1 @ 0x2ef4a810
+ This is an off-heap packed object occupying 16 bytes on the heap
+ The native memory is allocated at 0x35de1cc
+ The packed data is 8 bytes long
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 98 (0x62)
+ public com.ibm.dump.tests.types.packed.NestedPacked2 nestedPacked2Field = com/ibm/dump/tests/types/packed/NestedPacked2 packed @ 0x35de1d0
+
+ references:
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"16","24"}; // object header size on 32, 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/NestedPacked1";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+// passed &= o.skipLimitedToLineContaining(7, "This is an on-heap packed object");
+ passed &= o.skipLimitedToLineContaining(7, "This is an ");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+// passed &= o.skipLimitedToLineContaining(1, "This is a derived packed object");
+// passed &= o.skipLimitedToLineContaining(1, "target object: com/ibm/dump/tests/types/packed/NestedPacked @ 0x");
+// passed &= o.skipLimitedToLineContaining(1, "target offset: 0x");
+// passed &= o.skipLimitedToLineContaining(1, "showing fields for com/ibm/dump/tests/types/packed/NestedPacked1 packed @ 0x");
+// passed &= o.skipToLineContainingListOfReferencesAndCheckCount(6, 1);
+
+// passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/NestedPacked1 @");
+ passed &= o.skipLimitedToLineContaining(14, "com/ibm/dump/tests/types/packed/NestedPacked1 @");
+// passed &= o.skipLimitedToLineContaining(1, "This is an off-heap packed object");
+ passed &= o.skipLimitedToLineContaining(1, "This is an ");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+// passed &= o.skipLimitedToLineContaining(1, "The native memory is allocated at 0x");
+// passed &= o.skipLimitedToLineContaining(1, "The packed data is ");
+// passed &= o.skipToLineContainingListOfReferencesAndCheckCount(6, 0);
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest7NestedPackedChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest7NestedPackedChecker.java
new file mode 100644
index 00000000000..0a628a172e9
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest7NestedPackedChecker.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest7NestedPackedChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/NestedPacked".
+ *
+ * The expected output is as follows:
+ *
+info class com/ibm/dump/tests/types/packed/NestedPacked
+name = com/ibm/dump/tests/types/packed/NestedPacked
+
+ ID = 0x3d8fb00 superID = 0x3bd3f00
+ classLoader = 0x2ef39d70 modifiers: public final
+
+ This is a packed class
+
+ number of instances: 2
+ total size of instances on the heap: 40 bytes
+
+Inheritance chain....
+
+ com/ibm/jvm/packed/PackedObject
+ com/ibm/dump/tests/types/packed/NestedPacked
+
+Fields......
+
+ static fields for "com/ibm/dump/tests/types/packed/NestedPacked"
+ public static int staticIntField = 99 (0x63)
+
+ non-static fields for "com/ibm/dump/tests/types/packed/NestedPacked"
+ public int intField
+ public com.ibm.dump.tests.types.packed.NestedPacked1 nestedPacked1Field
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"40","64", "48"}; // on- + off-heap 32, on- + off-heap 64
+
+
+ boolean passed = true;
+
+ String command = "info class com/ibm/dump/tests/types/packed/NestedPacked";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/NestedPacked".
+ *
+ * The expected output is as follows:
+ *
+ * BUT can appear in either order :-(
+ *
+x/j com/ibm/dump/tests/types/packed/NestedPacked
+ heap #1 - name: Generational@689b98
+
+ static fields for "com/ibm/dump/tests/types/packed/NestedPacked"
+ public static int staticIntField = 99 (0x63)
+
+ com/ibm/dump/tests/types/packed/NestedPacked @ 0x2ef4a840
+ This is an on-heap packed object occupying 24 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 99 (0x63)
+ public com.ibm.dump.tests.types.packed.NestedPacked1 nestedPacked1Field = com/ibm/dump/tests/types/packed/NestedPacked1 packed @ 0x2ef4a850
+
+ references:
+ 0x2ef4a840
+
+ com/ibm/dump/tests/types/packed/NestedPacked @ 0x2ef4a878
+ This is an off-heap packed object occupying 16 bytes on the heap
+ The native memory is allocated at 0x359e1c8
+ The packed data is 12 bytes long
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 99 (0x63)
+ public com.ibm.dump.tests.types.packed.NestedPacked1 nestedPacked1Field = com/ibm/dump/tests/types/packed/NestedPacked1 packed @ 0x359e1cc
+
+ references:
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"24","16","40","24", "32"}; // on-heap 32, off-heap 32, on-heap 64, off-heap 64
+
+ String command = "x/j com/ibm/dump/tests/types/packed/NestedPacked";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(7, "This is an ");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+// passed &= o.skipToLineContainingListOfReferencesAndCheckCount(6, 1);
+
+ passed &= o.skipLimitedToLineContaining(12, "com/ibm/dump/tests/types/packed/NestedPacked @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an ");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+// passed &= o.skipLimitedToLineContaining(1, "The native memory is allocated at 0x");
+// passed &= o.skipLimitedToLineContaining(1, "The packed data is ");
+// passed &= o.skipToLineContainingListOfReferencesAndCheckCount(6, 0);
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest8NestedPackedMixedChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest8NestedPackedMixedChecker.java
new file mode 100644
index 00000000000..a96e9a767a7
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest8NestedPackedMixedChecker.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest8NestedPackedMixedChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/NestedPackedMixed".
+ *
+ * The expected output is as follows:
+ *
+info class com/ibm/dump/tests/types/packed/NestedPackedMixed
+name = com/ibm/dump/tests/types/packed/NestedPackedMixed
+
+ ID = 0x3a40200 superID = 0x3883f00
+ classLoader = 0x2ef39e28 modifiers: public final
+
+ This is a packed class
+
+ number of instances: 1
+ total size of instances on the heap: 40 bytes
+
+Inheritance chain....
+
+ com/ibm/jvm/packed/PackedObject
+ com/ibm/dump/tests/types/packed/NestedPackedMixed
+
+Fields......
+
+ "com/ibm/dump/tests/types/packed/NestedPackedMixed" has no static fields
+
+ non-static fields for "com/ibm/dump/tests/types/packed/NestedPackedMixed"
+ public int intField
+ public com.ibm.dump.tests.types.notpacked.NotPackedPrimitives npp
+ public com.ibm.dump.tests.types.packed.NestedPackedMixed1 nestedPacked1Field
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"24","16","40","24", "72"}; // on-heap 32, off-heap 32, on-heap 64, off-heap 64, nocr
+
+
+ boolean passed = true;
+
+ String command = "info class com/ibm/dump/tests/types/packed/NestedPackedMixed";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("1",4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes,8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/NestedPackedMixed".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/NestedPackedMixed
+ heap #1 - name: Generational@5860f0
+
+ "com/ibm/dump/tests/types/packed/NestedPackedMixed" has no static fields
+
+ com/ibm/dump/tests/types/packed/NestedPackedMixed @ 0x2ef48a88
+ This is an on-heap packed object occupying 40 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ public int intField = 99 (0x63)
+ public com.ibm.dump.tests.types.notpacked.NotPackedPrimitives npp = @ 0x2ef48ab0
+ public com.ibm.dump.tests.types.packed.NestedPackedMixed1 nestedPacked1Field = com/ibm/dump/tests/types/packed/NestedPackedMixed1 packed @ 0x2ef48a9c
+
+ references:
+ 0x2ef48a88 0x2ef48ab0 0x2ef48ae0
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"24","16","40","24", "72"}; // on-heap 32, off-heap 32, on-heap 64, off-heap 64, no cr
+
+ String command = "x/j com/ibm/dump/tests/types/packed/NestedPackedMixed";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipToLineContainingListOfReferencesAndCheckCount(8, 3);
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest9PackedIntsArrayChecker.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest9PackedIntsArrayChecker.java
new file mode 100644
index 00000000000..aa12f2a060d
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/system_dump_packed_objects/SystemDumpTest9PackedIntsArrayChecker.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.system_dump_packed_objects;
+
+import java.io.IOException;
+
+import com.ibm.dump.tests.OutputFile;
+
+public class SystemDumpTest9PackedIntsArrayChecker {
+
+ /**
+ * Check through the output looking for the output from "info class com/ibm/dump/tests/types/packed/PackedIntsArray".
+ *
+ * The expected output is as follows:
+ *
+> info class com/ibm/dump/tests/types/packed/PackedIntsArray
+name = com/ibm/dump/tests/types/packed/PackedIntsArray
+
+ ID = 0xf076cf0 superID = 0xf010650
+ classLoader = modifiers: No modifiers available
+
+ This is a packed class
+
+ number of instances: 2
+ total size of instances on the heap: 56 bytes
+
+
+ * @throws IOException
+ */
+
+ public static boolean checkInfoClassCommand(String fileName) throws IOException {
+ String[] validTotalSizes = {"56","80", "64"}; // 32 , 64
+
+
+ String command = "info class com/ibm/dump/tests/types/packed/PackedIntsArray";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "This is a packed class");
+ passed &= o.skipLimitedToLineContaining(2, "number of instances");
+ passed &= o.linePassesCheckForStringAtWord("2", 4);
+ passed &= o.skipLimitedToLineContaining(1, "total size of instances on the heap");
+ passed &= o.linePassesCheckForStringsAtWord(validTotalSizes, 8);
+
+ return passed;
+ }
+
+ /**
+ * Check through the output looking for the output from "x/j com/ibm/dump/tests/types/packed/PackedIntsArray".
+ *
+ * The expected output is as follows:
+ *
+x/j com/ibm/dump/tests/types/packed/PackedIntsArray
+ heap #1 - name: Generational@689b98
+
+ "com/ibm/dump/tests/types/packed/PackedIntsArray" has no static fields
+
+ com/ibm/dump/tests/types/packed/PackedIntsArray @ 0x2ef4a9c0
+ This is an on-heap packed object occupying 40 bytes on the heap
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ @Length(2) public com.ibm.jvm.packed.types.PackedInt[] piArray1 = com/ibm/jvm/packed/types/PackedInt[2] packed @ 0x2ef4a9cc
+ @Length(5) public com.ibm.jvm.packed.types.PackedInt[] piArray2 = com/ibm/jvm/packed/types/PackedInt[5] packed @ 0x2ef4a9d4
+
+ references:
+ 0x2ef4a9c0
+
+ com/ibm/dump/tests/types/packed/PackedIntsArray @ 0x2ef4a9e8
+ This is an off-heap packed object occupying 16 bytes on the heap
+ The native memory is allocated at 0x68a170
+ The packed data is 28 bytes long
+ fields inherited from "com/ibm/jvm/packed/PackedObject":
+ declared fields:
+ @Length(2) public com.ibm.jvm.packed.types.PackedInt[] piArray1 = com/ibm/jvm/packed/types/PackedInt[2] packed @ 0x68a170
+ @Length(5) public com.ibm.jvm.packed.types.PackedInt[] piArray2 = com/ibm/jvm/packed/types/PackedInt[5] packed @ 0x68a178
+
+ references:
+
+ * @throws IOException
+ */
+
+ public static boolean checkXJClassCommand(String fileName) throws IOException {
+ String[] validSizes = {"40","16", "48", "56", "24"}; // on-heap 32, on-heap 64, nocr
+
+
+ String command = "x/j com/ibm/dump/tests/types/packed/PackedIntsArray";
+ System.err.println("\nChecking the output from the command \"" + command + "\"");
+
+ OutputFile o = new OutputFile(fileName);
+ if (! o.skipUnlimitedToLineContaining(command) ) {
+ // if we cannot find this line, don't bother going any further
+ return false;
+ }
+
+ boolean passed = true;
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedIntsArray @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an on-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(3, "@Length(2) public com.ibm.jvm.packed.types.PackedInt$Array piArray1 = com/ibm/jvm/packed/types/PackedInt$Array[2] packed @ 0x");
+ passed &= o.skipLimitedToLineContaining(1, "@Length(5) public com.ibm.jvm.packed.types.PackedInt$Array piArray2 = com/ibm/jvm/packed/types/PackedInt$Array[5] packed @ 0x");
+
+ passed &= o.skipLimitedToLineContaining(6, "com/ibm/dump/tests/types/packed/PackedIntsArray @");
+ passed &= o.skipLimitedToLineContaining(1, "This is an off-heap packed object");
+ passed &= o.linePassesCheckForStringsAtWord(validSizes,8);
+ passed &= o.skipLimitedToLineContaining(1, "The native memory is allocated at 0x");
+ passed &= o.skipLimitedToLineContaining(1, "The packed data is ");
+ passed &= o.skipLimitedToLineContaining(3, "@Length(2) public com.ibm.jvm.packed.types.PackedInt$Array piArray1 = com/ibm/jvm/packed/types/PackedInt$Array[2] packed @ 0x");
+ passed &= o.skipLimitedToLineContaining(1, "@Length(5) public com.ibm.jvm.packed.types.PackedInt$Array piArray2 = com/ibm/jvm/packed/types/PackedInt$Array[5] packed @ 0x");
+
+ return passed;
+ }
+
+
+
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/timestamp/CreateDump.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/timestamp/CreateDump.java
new file mode 100644
index 00000000000..06b5b09fc17
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/timestamp/CreateDump.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.timestamp;
+
+
+public class CreateDump {
+
+ public static void main(String[] args) {
+
+ try {
+ java.lang.Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+
+ System.out.println("com.ibm.dump.tests.timestamp.CreateJavaCore: nanotime before dump ###" + java.lang.System.nanoTime() + "###");
+
+ try {
+ java.lang.Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+
+ try {
+ throw new com.ibm.dump.tests.timestamp.TestException();
+ } catch (Exception e) {
+ }
+
+ try {
+ java.lang.Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+
+ System.out.println("com.ibm.dump.tests.timestamp.CreateJavaCore: nanotime after dump ###" + java.lang.System.nanoTime() + "###");
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/timestamp/TestException.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/timestamp/TestException.java
new file mode 100644
index 00000000000..37bec679c60
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/timestamp/TestException.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.timestamp;
+
+public class TestException extends Exception {
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/types/notpacked/NotPackedMixedTwoRefs.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/types/notpacked/NotPackedMixedTwoRefs.java
new file mode 100644
index 00000000000..0618bf6d41a
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/types/notpacked/NotPackedMixedTwoRefs.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+
+package com.ibm.dump.tests.types.notpacked;
+
+import com.ibm.dump.tests.types.notpacked.NotPackedPrimitives;
+
+public class NotPackedMixedTwoRefs {
+ public int intField;
+ public NotPackedPrimitives npp1;
+ public NotPackedPrimitives npp2;
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/types/notpacked/NotPackedPrimitives.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/types/notpacked/NotPackedPrimitives.java
new file mode 100644
index 00000000000..173b3053ff5
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/types/notpacked/NotPackedPrimitives.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.types.notpacked;
+
+public final class NotPackedPrimitives {
+ public byte byteField = 'a';
+ public boolean booleanField = true;
+ public char charField = 0xff;
+ public int intField = 99;
+ public float floatField = (float) 123.4;
+ public double doubleField = 123.4;
+ public long longField = 101L;
+ public int int2Field = 99;
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/dump/tests/version_info/CheckVersionString.java b/test/functional/RasapiTest/src/com/ibm/dump/tests/version_info/CheckVersionString.java
new file mode 100644
index 00000000000..d85fc48c1a9
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/dump/tests/version_info/CheckVersionString.java
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.dump.tests.version_info;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel.MapMode;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import com.ibm.dtfj.image.Image;
+import com.ibm.dtfj.image.ImageAddressSpace;
+import com.ibm.dtfj.image.ImageFactory;
+import com.ibm.dtfj.image.ImageProcess;
+import com.ibm.dtfj.java.JavaRuntime;
+import com.ibm.jvm.trace.format.api.TraceContext;
+
+/**
+ * This class checks the various RAS artifacts contain the correct version
+ * string. It is in java rather than perl so we can use DTFJ to read system and
+ * heap dumps and the trace formatter to read the binary trace files directly.
+ *
+ * It expects to be run by the JVM that generated the artifacts in the first
+ * place.
+ *
+ * @author hhellyer
+ *
+ */
+public class CheckVersionString {
+
+ /**
+ * Arguments passed via system properties rather than command line arguments
+ * so we don't have to write parsing code.
+ */
+ private static final String JAVACORE_FILE_PROPERTY = "java.file";
+ private static final String SYSTEMDUMP_FILE_PROPERTY = "system.file";
+ private static final String HEAPDUMP_FILE_PROPERTY = "heap.file";
+ private static final String HEAPDUMP_CLASSIC_FILE_PROPERTY = "classic.heap.file";
+ private static final String SNAPDUMP_FILE_PROPERTY = "snap.file";
+
+ private static final String SDK_VERSION = "sdk.version";
+
+ private static final DumpType[] allDumps = { new JavaDumpType(),
+ /*new SystemDumpType(), - Disabled until DDR is stable. */
+ new HeapDumpType(),
+ new ClassicHeapDumpType(), new SnapDumpType() };
+
+ private static Properties sysProps = System.getProperties();
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ // Check the version.properties file exists. If it
+ // doesn't the dumps cannot get the right version
+ // String anyway.
+ String versionFilePath = sysProps.getProperty("java.home")
+ + File.separator + "lib" + File.separator
+ + "version.properties";
+ File versionFile = new File(versionFilePath);
+ if (!versionFile.exists()) {
+ System.err
+ .println("Package build does not contain " + versionFilePath);
+ System.err
+ .println("This should be present to indicate the build level of the fully packaged build of JVM and class libraries.");
+ System.exit(1);
+ }
+ Properties versionProperties = new Properties();
+ try {
+ versionProperties.load(new FileInputStream(versionFile));
+ } catch (FileNotFoundException e) {
+ // We don't expect this to happen as we've already checked the file
+ // exists.
+ System.err
+ .println("Package build does not contain " + versionFilePath);
+ System.err
+ .println("This should be present to indicate the build level of the fully packaged build of JVM and class libraries.");
+ e.printStackTrace();
+ System.exit(1);
+ } catch (IOException e) {
+ System.err.println("Unable to read " + versionFilePath);
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ final String sdkVersion = versionProperties.getProperty(SDK_VERSION);
+ if (sdkVersion == null) {
+ System.err.println(SDK_VERSION + " property in " + versionFilePath
+ + " was missing.");
+ System.err
+ .println("This should be present to indicate the build level of the fully packaged build of JVM and class libraries.");
+ System.exit(1);
+ }
+
+ Set failures = new HashSet();
+ // Check each artifact exists and contains the right data.
+ for (int i = 0; i < allDumps.length; i++) {
+ String error = checkDumpProperty(allDumps[i].getPropertyName(),
+ sysProps);
+ if (error != null) {
+ failures.add(error);
+ }
+ }
+ if (!failures.isEmpty()) {
+ Iterator fails = failures.iterator();
+ while (fails.hasNext()) {
+ System.err.println(fails.next());
+ }
+ System.exit(1);
+ }
+
+ Map versions = new HashMap();
+
+ // Keyed list for printing on error messages.
+ StringBuffer keyedVersions = new StringBuffer();
+
+ for (int i = 0; i < allDumps.length; i++) {
+ String versionString = allDumps[i].getVersionString();
+ keyedVersions.append(allDumps[i].getPropertyName());
+ keyedVersions.append(" : '");
+ keyedVersions.append(versionString);
+ keyedVersions.append("'\n");
+ System.err.println(allDumps[i].getPropertyName() + " : "
+ + versionString);
+ versions.put(allDumps[i].getPropertyName(), versionString);
+ }
+ // Check all versions are the same (after extraction) and that they all
+ // contain
+ // the contents of version.properties.
+ Iterator results = versions.values().iterator();
+ String version = results.next();
+ while (results.hasNext()) {
+ String nextVersion = results.next();
+ if (!version.equals(nextVersion)) {
+ System.err
+ .println("Version strings from all artifacts did not match. The strings were:\n"
+ + keyedVersions);
+ System.exit(1);
+ break;
+ }
+ version = nextVersion;
+ }
+
+ // Finally the version string must contain the contends of the sdk.version property
+ // from version.properties.
+ if (!version.contains(sdkVersion)) {
+ System.err
+ .println("The version strings did not contain the value of the sdk.version property in "
+ + versionFilePath
+ + "\n"
+ + "The value of sdk.version was "
+ + sdkVersion
+ + "\n"
+ + "The version strings all matched and were: "
+ + version);
+ System.exit(1);
+ }
+ System.out.println("Version string checks passed.");
+ System.exit(0);
+ }
+
+ private static String checkDumpProperty(String property, Properties sysProps) {
+ if (sysProps.getProperty(property) == null) {
+ return "Required -D parameter: " + property + " not set.";
+ }
+ File file = new File(sysProps.getProperty(property));
+ if (!file.exists()) {
+ return "Filed specified by " + property + " does not exist.";
+ }
+ return null;
+ }
+
+ private static abstract class DumpType {
+
+ private final String propertyName;
+
+ protected DumpType(String propName) {
+ propertyName = propName;
+ }
+
+ public abstract String getVersionString();
+
+ public String getPropertyName() {
+ return propertyName;
+ }
+ }
+
+ private static class SnapDumpType extends DumpType {
+
+ protected SnapDumpType() {
+ super(SNAPDUMP_FILE_PROPERTY);
+ }
+
+ @Override
+ public String getVersionString() {
+ String fileName = sysProps.getProperty(getPropertyName());
+ File file = new File(fileName);
+ FileInputStream f;
+ try {
+ f = new FileInputStream(file);
+ ByteBuffer data = f.getChannel().map(MapMode.READ_ONLY, 0,
+ file.length());
+ String j9TraceFormat_dat = sysProps.getProperty("java.home")
+ + "/lib/J9TraceFormat.dat";
+ TraceContext context = TraceContext.getContext(data,
+ new FileInputStream(new File(j9TraceFormat_dat)));
+ return context.getVmVersionString();
+ } catch (FileNotFoundException e) {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ private static class SystemDumpType extends DTFJDumpType {
+
+ protected SystemDumpType() {
+ super(SYSTEMDUMP_FILE_PROPERTY,
+ "com.ibm.dtfj.image.j9.ImageFactory");
+ }
+
+ public String getVersionString() {
+ String version = super.getVersionString();
+ if (version == null) {
+ return version;
+ }
+ /*
+ * The version string looks like:
+ * Java(TM) SE Runtime Environment(build JRE 1.6.0 IBM J9 2.6 Windows XP x86-32 build 20100901_064112 (pwi3260sr9-20100818_03(SR9)))
+ * IBM J9 VM(JRE 1.6.0 IBM J9 2.6 Windows XP x86-32 20100901_064112 (JIT enabled, AOT enabled)
+ * J9VM - VM JIT - dev_20100825_16819 GC -
+ * R26_head_20100831_1631_B64043) but we only want this bit: JRE 1.6.0 IBM J9 2.6 Windows XP x86-32 build 20100901_064112 (pwi3260sr9-20100818_03(SR9))
+ */
+ String prefix = "Java(TM) SE Runtime Environment(build ";
+ int start = version.indexOf(prefix) + prefix.length();
+ int end = version.indexOf(")))") + 2;
+ if( start > -1 && end > -1 && end > start) {
+ version = version.substring(start, end);
+ }
+ return version;
+ }
+ }
+
+ private static class HeapDumpType extends DTFJDumpType {
+
+ protected HeapDumpType() {
+ super(HEAPDUMP_FILE_PROPERTY, "com.ibm.dtfj.phd.PHDImageFactory");
+ }
+ }
+
+ private abstract static class DTFJDumpType extends DumpType {
+
+ private final String factoryName;
+
+ protected DTFJDumpType(String propertyName, String factoryName) {
+ super(propertyName);
+ this.factoryName = factoryName;
+ }
+
+ @Override
+ public String getVersionString() {
+ String fileName = sysProps.getProperty(getPropertyName());
+ File file = new File(fileName);
+ String version = null;
+ try {
+ Class factoryClass = (Class)Class.forName(factoryName);
+ ImageFactory factory = factoryClass
+ .newInstance();
+ Image image = factory.getImage(file);
+ Iterator asItr = image.getAddressSpaces();
+ while (asItr.hasNext() && version == null) {
+ Object nextAS = asItr.next();
+ if (!(nextAS instanceof ImageAddressSpace)) {
+ continue;
+ }
+ ImageAddressSpace as = (ImageAddressSpace) nextAS;
+ Iterator psItr = as.getProcesses();
+ while (psItr.hasNext() && version == null) {
+ Object nextPS = psItr.next();
+ if (!(nextPS instanceof ImageProcess)) {
+ continue;
+ }
+ ImageProcess ps = (ImageProcess) nextPS;
+ Iterator rtItr = ps.getRuntimes();
+ while (rtItr.hasNext() && version == null) {
+ Object nextRT = rtItr.next();
+ if (!(nextRT instanceof JavaRuntime)) {
+ continue;
+ }
+ JavaRuntime rt = (JavaRuntime) nextRT;
+ version = rt.getVersion();
+ }
+ }
+ }
+ } catch (Exception e) {
+ System.err
+ .println("Exception getting version information from system dump: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ if (version == null) {
+ return null;
+ }
+ return version;
+ }
+ }
+
+ private static class JavaDumpType extends TextDumpType {
+
+ private static final String EYECATCHER = "1CIJAVAVERSION ";
+
+ protected JavaDumpType() {
+ super(JAVACORE_FILE_PROPERTY, EYECATCHER);
+ }
+ }
+
+ private static class ClassicHeapDumpType extends TextDumpType {
+
+ private static final String EYECATCHER = "// Version: ";
+
+ protected ClassicHeapDumpType() {
+ super(HEAPDUMP_CLASSIC_FILE_PROPERTY, EYECATCHER);
+ }
+
+ }
+
+ private abstract static class TextDumpType extends DumpType {
+
+ private final String eyeCatcher;
+
+ protected TextDumpType(String propertyName, String eyeCatcher) {
+ super(propertyName);
+ this.eyeCatcher = eyeCatcher;
+ }
+
+ @Override
+ public String getVersionString() {
+ // Find the string that starts 1CIJAVAVERSION
+ // and return the contents of that line.
+ String fileName = sysProps.getProperty(getPropertyName());
+ File file = new File(fileName);
+ FileReader f;
+ String version = null;
+ try {
+ f = new FileReader(file);
+ BufferedReader in = new BufferedReader(f);
+ String line = in.readLine();
+ while (line != null) {
+ if (line.startsWith(eyeCatcher)) {
+ version = line.substring(eyeCatcher.length());
+ break;
+ }
+ line = in.readLine();
+ }
+ } catch (FileNotFoundException e) {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ }
+ return version;
+ }
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIBasicTests.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIBasicTests.java
new file mode 100644
index 00000000000..93f091ec1a3
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIBasicTests.java
@@ -0,0 +1,1051 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import static com.ibm.jvm.ras.tests.DumpAPISuite.deleteFile;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getContentType;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getFilesByPattern;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.isZOS;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import com.ibm.jvm.InvalidDumpOptionException;
+import com.ibm.jvm.ras.tests.DumpAPISuite.DumpType;
+
+public class DumpAPIBasicTests extends TestCase {
+
+ private long uid = System.currentTimeMillis();
+
+ // Record the files created by each testcase here so we can delete them
+ // later. Otherwise we will fill the disk up pretty quickly. While we check
+ // that the right kind of dump was created for each call we do any further
+ // validity checking on the dumps themselves. This test is just checking the
+ // API does what it should not that the dumps themselves are correct.
+ private Set fileNames;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ fileNames = new HashSet();
+ // This isn't to free space, it's to trigger GC tracepoints so we don't get empty snap dumps!
+ System.gc();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ for( String fileName: fileNames) {
+ deleteFile(fileName, this.getName());
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testJavaDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.JavaDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ private void addNewFilesToDelete(String[] beforeFileNames,
+ String[] afterFileNames) {
+ for( String after : afterFileNames ) {
+ boolean newFile = true;
+ for( String before : beforeFileNames ) {
+ if( before.equals(after) ) {
+ newFile = false;
+ break;
+ }
+ }
+ if( newFile ) {
+ fileNames.add(after);
+ }
+ }
+ }
+
+ public void testJavaDumpWithFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "javacore."+ getName() + "." + uid + ".txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The javacore file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+ assertEquals("Expected javacore to be written to file: " + expectedName + " but was written to " + javacoreName, expectedName, javacoreName);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+ DumpType type = getContentType(javacoreFile);
+ assertEquals("Expected file " + javacoreName + " to contain a java core but content type was: " + type, DumpType.JAVA_TYPE, type);
+ }
+
+ /** Test what happens when a filename includes options e.g "heap.phd,opts=CLASSIC"
+ */
+ public void testJavaDumpWithOptions() {
+ String[] options = {
+ ",exec=gdb",
+ ",file=foo.dmp",
+ ",filter=java/lang/OutOfMemoryError",
+ ",opts=CLASSIC",
+ ",priority=500",
+ ",range=1..6",
+ ",request=exclusive",
+ ",suspendwith=2",
+ };
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "javacore."+ getName() + "." + uid + ".txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The java core file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check none of these options works in a file name.
+ for( String option : options ) {
+ String javaDumpName = null;
+ try {
+ javaDumpName = com.ibm.jvm.Dump.javaDumpToFile(expectedName + option);
+ fail("Expected InvalidDumpOption exception to be thrown instead " + javaDumpName + " was written when specifying: " + option);
+ } catch (InvalidDumpOptionException e ) {
+ }
+ }
+ }
+
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testJavaDumpNullFile() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(null);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ // Check the generated file really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ // Check content
+ DumpType type = getContentType(javacoreFile);
+ assertEquals("Expected file " + javacoreName + " to contain a java core but content type was: " + type, DumpType.JAVA_TYPE, type);
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testJavaDumpEmptyFile() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile("");
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ // Check the generated file really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ // Check content
+ DumpType type = getContentType(javacoreFile);
+ assertEquals("Expected file " + javacoreName + " to contain a java core but content type was: " + type, DumpType.JAVA_TYPE, type);
+
+ }
+
+ /**
+ * Test a java dump isn't generated when the path is "-"
+ */
+ public void testJavaDumpToDashFile() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile("-");
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ // Check the number of files has stayed the same
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+
+ }
+
+ /* Test we relocate files if they clash with an existing file, but only once! */
+ public void testJavaDumpWithSameFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "javacore."+ getName() + "." + uid + ".txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The javacore file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+ assertEquals("Expected javacore to be written to file: " + expectedName + " but was written to " + javacoreName, expectedName, javacoreName);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+ // Check we get a different name the second time.
+
+ String javacoreName2 = null;
+ try {
+ javacoreName2 = com.ibm.jvm.Dump.javaDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName2);
+ fileNames.add(javacoreName2);
+ assertFalse(
+ "Expected second dump file to be written to a different location. Original dump: "
+ + javacoreName + " second dump: " + javacoreName2, javacoreName.equals(javacoreName2));
+ // Check it really exists.
+ File javacoreFile2 = new File(javacoreName2);
+ assertTrue("Failed to find files " + javacoreName2
+ + " after requesting " + javacoreName + " a second time.",
+ javacoreFile2.exists());
+
+ // Now check this file is replaced if we end up writing to it again
+ // the same way.
+ long timestamp2 = javacoreFile2.lastModified();
+
+ // Some timestamps are only down to the second on some platforms.
+ // Dumps can happen quicker than that.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e){
+ // Ignore.
+ }
+
+ // Check we get a different name the second time.
+ String javacoreName3 = null;
+ try {
+ javacoreName3 = com.ibm.jvm.Dump.javaDumpToFile(expectedName);
+ fail("Expected to fail when we tried overwriting the file we failed over to.");
+ } catch (InvalidDumpOptionException e ) {
+ System.out.println(e);
+ System.out.println("reach here");
+ }
+
+ }
+
+ /*
+ * Test a heap dump is generated from the standard com.ibm.jvm.Dump.HeapDump()
+ * call.
+ */
+ public void testHeapDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "heapdump\\..*\\.phd";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.HeapDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ public void testHeapDumpWithFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "heapdump."+ getName() + "." + uid + ".phd";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The javacore file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String heapDumpName = null;
+ try {
+ heapDumpName = com.ibm.jvm.Dump.heapDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", heapDumpName);
+ fileNames.add(heapDumpName);
+ assertEquals("Expected javacore to be written to file: " + expectedName + " but was written to " + heapDumpName, expectedName, heapDumpName);
+
+ // Check it really exists.
+ File heapDumpFile = new File(heapDumpName);
+ assertTrue("Failed to find files " + heapDumpName + " after requesting " + heapDumpName, heapDumpFile.exists());
+
+ // Check content
+ DumpType type = getContentType(heapDumpFile);
+ assertEquals("Expected file " + heapDumpName + " to contain a heap dump but content type was: " + type, DumpType.PHD_HEAP_TYPE, type);
+
+ }
+
+ /**
+ * Test what happens when a filename includes options e.g "heap.phd,opts=CLASSIC"
+ */
+ public void testHeapDumpWithOptions() {
+ String[] options = {
+ ",exec=gdb",
+ ",file=foo.dmp",
+ ",filter=java/lang/OutOfMemoryError",
+ ",opts=CLASSIC",
+ ",priority=500",
+ ",range=1..6",
+ ",request=exclusive",
+ ",suspendwith=2",
+ };
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "heapdump."+ getName() + "." + uid + ".phd";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The heap dump file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check none of these options works in a file name.
+ for( String option : options ) {
+ String heapDumpName = null;
+ try {
+ heapDumpName = com.ibm.jvm.Dump.heapDumpToFile(expectedName + option);
+ fail("Expected InvalidDumpOption exception to be thrown instead " + heapDumpName + " was written when specifying: " + option);
+ } catch (InvalidDumpOptionException e ) {
+ }
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testHeapDumpNullFile() {
+ String userDir = System.getProperty("user.dir");
+ String heapDumpPattern = "heapdump\\..*\\.phd";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, heapDumpPattern);
+ int beforeCount = beforeFileNames.length;
+
+ String heapDumpName = null;
+ try {
+ heapDumpName = com.ibm.jvm.Dump.heapDumpToFile(null);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected heapdump filename to be returned, not null", heapDumpName);
+ fileNames.add(heapDumpName);
+
+ // Check the generated file really exists.
+ File heapDumpFile = new File(heapDumpName);
+ assertTrue("Failed to find files " + heapDumpName + " after requesting " + heapDumpName, heapDumpFile.exists());
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, heapDumpPattern);
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ // Check content
+ DumpType type = getContentType(heapDumpFile);
+ assertEquals("Expected file " + heapDumpName + " to contain a heap dump but content type was: " + type, DumpType.PHD_HEAP_TYPE, type);
+ }
+
+ /**
+ * Test a heap dump isn't generated when the path is "-"
+ */
+ public void testHeapDumpToDashFile() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "heap\\..*\\.phd";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String heapName = null;
+ try {
+ heapName = com.ibm.jvm.Dump.heapDumpToFile("-");
+ fail("Expected InvalidDumpOption exception to be thrown filename " + heapName + " was returned");
+ } catch (InvalidDumpOptionException e ) {
+ // Pass
+ }
+ }
+
+ /* Test we relocate files if they clash with an existing file, but only once! */
+ public void testHeapDumpWithSameFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "heapdump."+ getName() + "." + uid + ".phd";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The heapdump file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String heapDumpName = null;
+ try {
+ heapDumpName = com.ibm.jvm.Dump.heapDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected heapdump filename to be returned, not null", heapDumpName);
+ fileNames.add(heapDumpName);
+ assertEquals("Expected heapdump to be written to file: " + expectedName + " but was written to " + heapDumpName, expectedName, heapDumpName);
+
+ // Check it really exists.
+ File heapdumpFile = new File(heapDumpName);
+ assertTrue("Failed to find files " + heapDumpName + " after requesting " + heapDumpName, heapdumpFile.exists());
+
+ // Check we get a different name the second time.
+ String heapdumpName2 = null;
+ try {
+ heapdumpName2 = com.ibm.jvm.Dump.heapDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected heapdump filename to be returned, not null", heapdumpName2);
+ fileNames.add(heapdumpName2);
+ assertFalse(
+ "Expected second dump file to be written to a different location. Original dump: "
+ + heapDumpName + " second dump: " + heapdumpName2, heapDumpName.equals(heapdumpName2));
+ // Check it really exists.
+ File heapdumpFile2 = new File(heapdumpName2);
+ assertTrue("Failed to find files " + heapdumpName2
+ + " after requesting " + heapDumpName + " a second time.",
+ heapdumpFile2.exists());
+
+ // Now check this file is replaced if we end up writing to it again
+ // the same way.
+ long timestamp2 = heapdumpFile2.lastModified();
+
+ // Some timestamps are only down to the second on some platforms.
+ // Dumps can happen quicker than that.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e){
+ // Ignore.
+ }
+
+ // Check we get a different name the second time.
+ String heapdumpName3 = null;
+ try {
+ heapdumpName3 = com.ibm.jvm.Dump.heapDumpToFile(expectedName);
+ fail("Expected to fail when we tried overwriting the file we failed over to.");
+ } catch (InvalidDumpOptionException e ) {
+ }
+
+ }
+
+
+ /**
+ * Test a snap dump is generated from the standard com.ibm.jvm.Dump.SnapDump()
+ * call.
+ */
+ public void testSnapDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "Snap\\..*\\.trc";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.SnapDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ public void testSnapDumpWithFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "snap."+ getName() + "." + uid + ".trc";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The snap file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String snapName = null;
+ try {
+ snapName = com.ibm.jvm.Dump.snapDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected snap filename to be returned, not null", snapName);
+ fileNames.add(snapName);
+ assertEquals("Expected snap to be written to file: " + expectedName + " but was written to " + snapName, expectedName, snapName);
+
+ // Check it really exists.
+ File snapFile = new File(snapName);
+ assertTrue("Failed to find files " + snapName + " after requesting " + snapName, snapFile.exists());
+
+ // Check content
+ DumpType type = getContentType(snapFile);
+ assertEquals("Expected file " + snapName + " to contain a snap trace but content type was: " + type, DumpType.SNAP_TYPE, type);
+
+ }
+
+ /**
+ * Test what happens when a filename includes options e.g "heap.phd,opts=CLASSIC"
+ */
+ public void testSnapDumpWithOptions() {
+ String[] options = {
+ ",exec=gdb",
+ ",file=foo.dmp",
+ ",filter=java/lang/OutOfMemoryError",
+ ",opts=CLASSIC",
+ ",priority=500",
+ ",range=1..6",
+ ",request=exclusive",
+ ",suspendwith=2",
+ };
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "Snap."+ getName() + "." + uid + ".trc";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The snap dump file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check none of these options works in a file name.
+ for( String option : options ) {
+ String snapDumpName = null;
+ try {
+ snapDumpName = com.ibm.jvm.Dump.snapDumpToFile(expectedName + option);
+ fail("Expected InvalidDumpOption exception to be thrown instead " + snapDumpName + " was written when specifying: " + option);
+ } catch (InvalidDumpOptionException e ) {
+ }
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testSnapDumpNullFile() {
+ String userDir = System.getProperty("user.dir");
+ String snapPattern = "Snap\\..*\\.trc";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, snapPattern);
+ int beforeCount = beforeFileNames.length;
+
+ String snapName = null;
+ try {
+ snapName = com.ibm.jvm.Dump.snapDumpToFile(null);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected snap filename to be returned, not null", snapName);
+ fileNames.add(snapName);
+
+ // Check the generated file really exists.
+ File snapFile = new File(snapName);
+ assertTrue("Failed to find files " + snapName + " after requesting " + snapName, snapFile.exists());
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, snapPattern);
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ // Check content
+ DumpType type = getContentType(snapFile);
+ assertEquals("Expected file " + snapName + " to contain a snap trace but content type was: " + type, DumpType.SNAP_TYPE, type);
+
+ }
+
+ /**
+ * Test a snap dump isn't generated when the path is "-"
+ */
+ public void testSnapDumpToDashFile() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "snap\\..*\\.trc";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String snapName = null;
+ try {
+ snapName = com.ibm.jvm.Dump.snapDumpToFile("-");
+ fail("Expected InvalidDumpOption exception to be thrown filename " + snapName + " was returned");
+ } catch (InvalidDumpOptionException e ) {
+ // Pass
+ }
+ }
+
+ /* Test we relocate files if they clash with an existing file, but only once! */
+ public void testSnapDumpWithSameFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "Snap."+ getName() + "." + uid + ".trc";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The Snap file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String snapName = null;
+ try {
+ snapName = com.ibm.jvm.Dump.snapDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+ assertNotNull("Expected Snap filename to be returned, not null", snapName);
+ fileNames.add(snapName);
+ assertEquals("Expected Snap to be written to file: " + expectedName + " but was written to " + snapName, expectedName, snapName);
+
+ // Check it really exists.
+ File snapFile = new File(snapName);
+ assertTrue("Failed to find files " + snapName + " after requesting " + snapName, snapFile.exists());
+
+ // Check we get a different name the second time.
+ String snapName2 = null;
+ try {
+ snapName2 = com.ibm.jvm.Dump.snapDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected Snap filename to be returned, not null", snapName2);
+ fileNames.add(snapName2);
+ assertFalse(
+ "Expected second dump file to be written to a different location. Original dump: "
+ + snapName + " second dump: " + snapName2, snapName.equals(snapName2));
+ // Check it really exists.
+ File snapFile2 = new File(snapName2);
+ assertTrue("Failed to find files " + snapName2
+ + " after requesting " + snapName + " a second time.",
+ snapFile2.exists());
+
+ // Now check this file is replaced if we end up writing to it again
+ // the same way.
+ long timestamp2 = snapFile2.lastModified();
+
+ // Some timestamps are only down to the second on some platforms.
+ // Dumps can happen quicker than that.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e){
+ // Ignore.
+ }
+
+ // Check we get a different name the second time.
+ String snapName3 = null;
+ try {
+ snapName3 = com.ibm.jvm.Dump.snapDumpToFile(expectedName);
+ fail("Expected to fail when we tried overwriting the file we failed over to.");
+ } catch (InvalidDumpOptionException e ) {
+ }
+
+// assertNotNull("Expected Snap filename to be returned, not null", snapName);
+// assertFalse(
+// "Expected third dump file to be written to a different location. Original dump: "
+// + snapName + " second dump: " + snapName3, snapName.equals(snapName3));
+// assertEquals(
+// "Expected third dump file to be written to the same location as the second location. Original dump: "
+// + snapName + " second dump: " + snapName2 + " third dump " + snapName3, snapName2, snapName3);
+// // Check it really exists.
+// File snapFile3 = new File(snapName3);
+// assertTrue("Failed to find files " + snapName3
+// + " after requesting " + snapName + " a second time.",
+// snapFile3.exists());
+//
+// // Now check this file is replaced if we end up writing to it again
+// // the same way.
+// long timestamp3 = snapFile3.lastModified();
+// System.err.println("Timestamp 3: " + timestamp3 + " > " + timestamp2);
+// assertTrue("Expected " + snapName3 + " to be updated by second dump to " + expectedName, timestamp3 > timestamp2);
+
+ }
+
+
+ /**
+ * Test a system dump is generated from the standard com.ibm.jvm.Dump.SystemDump()
+ * call.
+ */
+ public void testSystemDumpNoArgs() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "core\\..*\\.dmp";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.SystemDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ public void testSystemDumpWithFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "core."+ getName() + "." + uid + ".dmp";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The core file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String coreName = null;
+ try {
+ coreName = com.ibm.jvm.Dump.systemDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+ assertNotNull("Expected core filename to be returned, not null", coreName);
+ fileNames.add(coreName);
+ assertEquals("Expected core to be written to file: " + expectedName + " but was written to " + coreName, expectedName, coreName);
+
+ // Check it really exists.
+ File coreFile = new File(coreName);
+ assertTrue("Failed to find files " + coreName + " after requesting " + coreName, coreFile.exists());
+
+ // Check content
+ DumpType type = getContentType(coreFile);
+ assertEquals("Expected file " + coreName + " to contain a system core but content type was: " + type, DumpType.SYSTEM_TYPE, type);
+
+ }
+
+ /**
+ * Test what happens when a filename includes options e.g "heap.phd,opts=CLASSIC"
+ */
+ public void testSystemDumpWithOptions() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String[] options = {
+ ",exec=gdb",
+ ",file=foo.dmp",
+ ",filter=java/lang/OutOfMemoryError",
+ ",opts=CLASSIC",
+ ",priority=500",
+ ",range=1..6",
+ ",request=exclusive",
+ ",suspendwith=2",
+ };
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "core."+ getName() + "." + uid + ".dmp";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The core dump file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check none of these options works in a file name.
+ for( String option : options ) {
+ String coreDumpName = null;
+ try {
+ coreDumpName = com.ibm.jvm.Dump.systemDumpToFile(expectedName + option);
+ fail("Expected InvalidDumpOption exception to be thrown instead " + coreDumpName + " was written when specifying: " + option);
+ } catch (InvalidDumpOptionException e ) {
+ }
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testSystemDumpNullFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+ String corePattern = "core\\..*\\.dmp";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, corePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String coreName = null;
+ try {
+ coreName = com.ibm.jvm.Dump.systemDumpToFile(null);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected core filename to be returned, not null", coreName);
+ fileNames.add(coreName);
+
+ // Check the generated file really exists.
+ File coreFile = new File(coreName);
+ assertTrue("Failed to find files " + coreName + " after requesting " + coreName, coreFile.exists());
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, corePattern);
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ // Check content
+ DumpType type = getContentType(coreFile);
+ assertEquals("Expected file " + coreName + " to contain a system core but content type was: " + type, DumpType.SYSTEM_TYPE, type);
+
+ }
+
+ /**
+ * Test a core dump isn't generated when the path is "-"
+ */
+ public void testSystemDumpToDashFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+ String corePattern = "core\\..*\\.dmp";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, corePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String coreName = null;
+ try {
+ coreName = com.ibm.jvm.Dump.systemDumpToFile("-");
+ fail("Expected InvalidDumpOption exception to be thrown filename " + coreName + " was returned");
+ } catch (InvalidDumpOptionException e ) {
+ // Pass
+ }
+ }
+
+ /* Test we relocate files if they clash with an existing file, but only once! */
+ public void testSystemDumpWithSameFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "core."+ getName() + "." + uid + ".dmp";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The core file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ String coreName = null;
+ try {
+ coreName = com.ibm.jvm.Dump.systemDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+ assertNotNull("Expected core filename to be returned, not null", coreName);
+ fileNames.add(coreName);
+ assertEquals("Expected core to be written to file: " + expectedName + " but was written to " + coreName, expectedName, coreName);
+
+ // Check it really exists.
+ File coreFile = new File(coreName);
+ assertTrue("Failed to find files " + coreName + " after requesting " + coreName, coreFile.exists());
+
+ // Check we get a different name the second time.
+ String coreName2 = null;
+ try {
+ coreName2 = com.ibm.jvm.Dump.systemDumpToFile(expectedName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected core filename to be returned, not null", coreName2);
+ fileNames.add(coreName2);
+ assertFalse(
+ "Expected second dump file to be written to a different location. Original dump: "
+ + coreName + " second dump: " + coreName2, coreName.equals(coreName2));
+ // Check it really exists.
+ File coreFile2 = new File(coreName2);
+ assertTrue("Failed to find files " + coreName2
+ + " after requesting " + coreName + " a second time.",
+ coreFile2.exists());
+
+ // Now check this file is replaced if we end up writing to it again
+ // the same way.
+ long timestamp2 = coreFile2.lastModified();
+
+ // Some timestamps are only down to the second on some platforms.
+ // Dumps can happen quicker than that.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e){
+ // Ignore.
+ }
+
+ // Check we get a different name the second time.
+ String coreName3 = null;
+ try {
+ coreName3 = com.ibm.jvm.Dump.systemDumpToFile(expectedName);
+ fail("Expected to fail when we tried overwriting the file we failed over to.");
+ } catch (InvalidDumpOptionException e ) {
+ }
+
+// assertNotNull("Expected core filename to be returned, not null", coreName);
+// assertFalse(
+// "Expected third dump file to be written to a different location. Original dump: "
+// + coreName + " second dump: " + coreName3, coreName.equals(coreName3));
+// assertEquals(
+// "Expected third dump file to be written to the same location as the second location. Original dump: "
+// + coreName + " second dump: " + coreName2 + " third dump " + coreName3, coreName2, coreName3);
+// // Check it really exists.
+// File coreFile3 = new File(coreName3);
+// assertTrue("Failed to find files " + coreName3
+// + " after requesting " + coreName + " a second time.",
+// coreFile3.exists());
+//
+// // Now check this file is replaced if we end up writing to it again
+// // the same way.
+// long timestamp3 = coreFile3.lastModified();
+// System.err.println("Timestamp 3: " + timestamp3 + " > " + timestamp2);
+// assertTrue("Expected " + coreName3 + " to be updated by second dump to " + expectedName, timestamp3 > timestamp2);
+
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIQuerySetReset.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIQuerySetReset.java
new file mode 100644
index 00000000000..c09f267c84c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIQuerySetReset.java
@@ -0,0 +1,652 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import com.ibm.jvm.DumpConfigurationUnavailableException;
+import com.ibm.jvm.InvalidDumpOptionException;
+
+@SuppressWarnings("nls")
+public class DumpAPIQuerySetReset extends TestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private static void clearDumpOptions() {
+ String initialDumpOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("none");
+ } catch (InvalidDumpOptionException idoe) {
+ idoe.printStackTrace();
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ } catch (DumpConfigurationUnavailableException e) {
+ e.printStackTrace();
+ }
+
+ String afterNoneOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ if (0 != afterNoneOptions.length) {
+ fail("Expected an empty array of dump options but got: " + Arrays.toString(afterNoneOptions));
+ }
+ }
+
+ public void testSetNone() {
+ String initialDumpOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("none");
+ } catch (InvalidDumpOptionException idoe) {
+
+ } catch (DumpConfigurationUnavailableException e) {
+ e.printStackTrace();
+ }
+
+ String afterNoneOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ if (0 != afterNoneOptions.length) {
+ fail("Expected an empty array of dump options but got: " + Arrays.toString(afterNoneOptions));
+ }
+ }
+
+ public void testSetWhat() {
+ // clearDumpOptions();
+ try {
+ com.ibm.jvm.Dump.resetDumpOptions();
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("what");
+ } catch (InvalidDumpOptionException idoe) {
+ fail("-Xdump:what was expected to be permitted");
+ }
+ } catch (DumpConfigurationUnavailableException e) {
+ e.printStackTrace();
+ }
+ // -Xdump:what doesn't do anything but it would just be irritating if people couldn't
+ // use it to quickly print all available options.
+ }
+
+ // testQuery - set loads of options to get a huge buffer, query, check we get all the options back as expected
+ public void testQuery() {
+ clearDumpOptions();
+ String[] dumpTypes = { "java", "system", "heap", "tool", "console", "stack", "silent", "jit" };
+ String[] dumpEvents = { "systhrow", "uncaught", "gpf", "traceassert", "user", "abort", "vmstop" };
+ // The following events are omitted from the list above as they can affect the behaviour of the VM under test,
+ // e.g. "thrstart" will cause a dump to be triggered if another thread starts, and hence lock the dump configuration
+ // at an arbitrary point in time: "vmstart", "throw", "systhrow", "catch", "uncaught", "thrstart", "thrstop"
+ String[] dumpFilters = { "java/lang/OutOfMemoryError", "java/lang/NullPointerException", "made/up/Exception1",
+ "made/up/Exception2", "made/up/Exception3", "made/up/Exception4", "made/up/Exception5",
+ "made/up/Exception6", "made/up/Exception7" };
+
+ int count = populateDumpAgents(dumpTypes, dumpEvents, dumpFilters);
+
+ String dumpAgents[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertNotNull("Expected array of dump agents returned, not null", dumpAgents);
+ assertEquals("Expected " + count + " dump agents configured.", count, dumpAgents.length);
+
+ // Can probably have one function to validate two list of options match and re-use in lots of places.
+
+ int foundCount = checkDumpAgents(dumpTypes, dumpEvents, dumpFilters, dumpAgents);
+ assertEquals("Expected to find all the expected agents.", dumpAgents.length, foundCount);
+ clearDumpOptions();
+ }
+
+ /**
+ * Use the settings we are passed to generate all those combinations of dump
+ * agents.
+ * The arrays must be the same size as the arrays passed to populateDumpAgents,
+ * use null for any items which have been removed.
+ * @param dumpTypes
+ * @param dumpEvents
+ * @param dumpFilters
+ * @param dumpAgents
+ * @return
+ */
+ private static int checkDumpAgents(String[] dumpTypes, String[] dumpEvents, String[] dumpFilters, String[] dumpAgents) {
+ int checkCount = 0;
+ int foundCount = 0;
+ // System.err.println("Running checkDumpAgents...");
+ for (String type : dumpTypes) {
+ for (String event : dumpEvents) {
+ String eventPattern = "events=" + event;
+ for (String filter : dumpFilters) {
+ // Find a dump type agent for each line we added. Can't do an exact match as
+ // the agents add paths and re-order arguments.
+ String filterPattern = "filter=" + filter;
+ // 'label' is still accepted in options, but no longer used in reports
+ String labelPattern = ".*\\b(dsn|exec|file)=.*" + type + checkCount + ".*";
+ checkCount++;
+ if (type == null || event == null || filter == null) {
+ // This permutation should have been removed, still
+ // need to increment checkCount to kep the labels matching.
+ continue;
+ }
+ // System.err.println("Checking: " + type);
+ // System.err.println("Checking: " + eventPattern);
+ // System.err.println("Checking: " + filterPattern);
+ // System.err.println("Checking: " + labelPattern);
+ for (String agentString : dumpAgents) {
+ // System.err.println("Agent checked is: " + agentString);
+ if (!agentString.startsWith(type)) {
+ continue;
+ }
+ if (!agentString.contains(eventPattern)) {
+ continue;
+ }
+ if (!agentString.contains(filterPattern)) {
+ continue;
+ }
+ if (!agentString.matches(labelPattern)) {
+ continue;
+ }
+ foundCount++;
+ // System.err.println("found: " + agentString);
+ }
+ }
+ }
+ }
+ // System.err.println("Checked: " + checkCount);
+ return foundCount;
+ }
+
+ /**
+ * Use the settings we are passed to generate all combinations of dump agents.
+ */
+ private static int populateDumpAgents(String[] dumpTypes, String[] dumpEvents, String[] dumpFilters) {
+ int count = 0;
+
+ for (String type : dumpTypes) {
+ for (String event : dumpEvents) {
+ for (String filter : dumpFilters) {
+ // Create agents the dump system can't merge.
+ String options = type + ":events=" + event + ",filter=" + filter + ",label=" + type + count++;
+ try {
+ com.ibm.jvm.Dump.setDumpOptions(options);
+ } catch (InvalidDumpOptionException e) {
+ e.printStackTrace();
+ fail("Expected my dump options to work but got an InvalidDumpOptionException: " + e.getMessage());
+ } catch (DumpConfigurationUnavailableException e) {
+ e.printStackTrace();
+ fail("Expected my dump options to work but got an DumpConfigurationUnavailableException: " + e.getMessage());
+ }
+ }
+ }
+ }
+
+ return count;
+ }
+
+ // testSetNone - test all dumps of particular types can be removed.
+ public void testSetNoneByType() {
+ clearDumpOptions();
+
+ String[] dumpTypes = { "java", "system", "heap", "tool", "console", "stack", "silent", "jit" };
+ String[] dumpEvents = { "systhrow", "uncaught" }; // { "throw", "systhrow", "catch", "uncaught" };
+ String[] dumpFilters = { "java/lang/OutOfMemoryError", "java/lang/NullPointerException", "made/up/Exception1",
+ "made/up/Exception2", "made/up/Exception3", "made/up/Exception4", "made/up/Exception5",
+ "made/up/Exception6", "made/up/Exception7" };
+
+ int count = populateDumpAgents(dumpTypes, dumpEvents, dumpFilters);
+
+ String dumpAgents[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertNotNull("Expected array of dump agents returned, not null", dumpAgents);
+ assertEquals("Expected " + count + " dump agents configured.", count, dumpAgents.length);
+
+ String removalType = "heap";
+ try {
+ com.ibm.jvm.Dump.setDumpOptions(removalType + ":none");
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected to be able to remove all dump agents of type: " + removalType);
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Expected to be able to remove all dump agents of type: " + removalType);
+ }
+
+ String[] afterAgents = com.ibm.jvm.Dump.queryDumpOptions();
+ // System.out.println("Found " + afterAgents.length + " agents");
+ // for (String agent : afterAgents) {
+ // System.out.println("After: " + agent);
+ // }
+
+ // Validate the list of agents.
+ int foundCount = checkDumpAgents(
+ new String[] { "java", "system", null, "tool", "console", "stack", "silent", "jit" },
+ dumpEvents, dumpFilters, afterAgents);
+ assertEquals("Expected to find all the expected agents.", afterAgents.length, foundCount);
+ }
+
+ // testSetNone - test all dumps with certain options can be disabled
+ public void testSetNoneByOptions() {
+ clearDumpOptions();
+ String[] dumpTypes = { "java", "system", "heap", "console", "stack", "silent", "jit" };
+ String[] dumpEvents = { "systhrow", "uncaught" }; // { "throw", "systhrow", "catch", "uncaught" };
+ String[] dumpFilters = { "java/lang/OutOfMemoryError", "java/lang/NullPointerException", "made/up/Exception1",
+ "made/up/Exception2", "made/up/Exception3", "made/up/Exception4", "made/up/Exception5",
+ "made/up/Exception6", "made/up/Exception7" };
+
+ int count = populateDumpAgents(dumpTypes, dumpEvents, dumpFilters);
+
+ String dumpAgents[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertNotNull("Expected array of dump agents returned, not null", dumpAgents);
+ assertTrue("Expected " + count + " dump agents configured.", dumpAgents.length == count);
+
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("java+system+heap+console+stack+silent+jit:none:events=uncaught");
+ com.ibm.jvm.Dump.setDumpOptions("java+system+heap+console+stack+silent+jit:none:filter=made/up/Exception3");
+ com.ibm.jvm.Dump.setDumpOptions("java+system+heap+console+stack+silent+jit:none:filter=made/up/Exception5");
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected to be able to remove all dump agents by filter");
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Expected to be able to remove all dump agents by filter. Dump configuration was unavailable.");
+ }
+
+ String[] afterAgents = com.ibm.jvm.Dump.queryDumpOptions();
+ // System.out.println("Found " + afterAgents.length + " agents");
+ // for (String agent : afterAgents) {
+ // System.out.println("After: " + agent);
+ // }
+
+ // Validate the list of agents.
+ int foundCount = checkDumpAgents(dumpTypes,
+ new String[] { "systhrow", null },
+ new String[] {
+ "java/lang/OutOfMemoryError",
+ "java/lang/NullPointerException", "made/up/Exception1",
+ "made/up/Exception2", null, "made/up/Exception4", null,
+ "made/up/Exception6", "made/up/Exception7" },
+ afterAgents);
+ assertEquals("Expected to find all the expected agents.", afterAgents.length, foundCount);
+ }
+
+ // testSetNone - test all dumps of particular types with certain options can be disabled.
+ // public void testSetNoneByTypeAndOptions() {
+ // clearDumpOptions();
+ // String[] dumpTypes = {"java", "system", "heap", "console", "stack", "silent", "jit"};
+ // String[] dumpEvents = {"systhrow", "uncaught"};//{"throw", "systhrow", "catch", "uncaught"};
+ // String[] dumpFilters = {"java/lang/OutOfMemoryError", "java/lang/NullPointerException", "made/up/Exception1", "made/up/Exception2",
+ // "made/up/Exception3", "made/up/Exception4", "made/up/Exception5", "made/up/Exception6", "made/up/Exception7"};
+ //
+ // int count = populateDumpAgents(dumpTypes, dumpEvents, dumpFilters );
+ //
+ // String dumpAgents[] = com.ibm.jvm.Dump.queryDumpOptions();
+ // assertNotNull("Expected array of dump agents returned, not null", dumpAgents);
+ // assertTrue("Expected " + count + " dump agents configured.", dumpAgents.length == count);
+ //
+ // try {
+ // com.ibm.jvm.Dump.setDumpOptions("console:none:events=systhrow");
+ // com.ibm.jvm.Dump.setDumpOptions("console:none:filter=made/up/Exception2");
+ // com.ibm.jvm.Dump.setDumpOptions("console:none:filter=made/up/Exception7");
+ // } catch (InvalidDumpOptionException e) {
+ // fail("Expected to be able to remove all dump agents by filter");
+ // }
+ //
+ // String[] afterAgents = com.ibm.jvm.Dump.queryDumpOptions();
+ // System.out.println("Found " + afterAgents.length + " agents");
+ // for( String agent: afterAgents ) {
+ // System.out.println("After: " + agent);
+ // }
+ //
+ // // Validate the list of agents.
+ // int foundCount = checkDumpAgents(new String[] {"java", "system", "heap", null, "stack", "silent", "jit"},
+ // new String[] { null, "uncaught" }, new String[] {
+ // "java/lang/OutOfMemoryError",
+ // "java/lang/NullPointerException", "made/up/Exception1",
+ // null, "made/up/Exception3", "made/up/Exception4", "made/up/Exception5",
+ // "made/up/Exception6", null },
+ // afterAgents);
+ // assertEquals("Expected to find all the expected agents.", afterAgents.length, foundCount );
+ // }
+
+ // testReset - reset, query, clear with -Xdump:none (check cleared), reset again and query to see if we have the original settings
+ public void testReset() {
+ // Set the options back to the defaults.
+ clearDumpOptions();
+
+ try {
+ com.ibm.jvm.Dump.resetDumpOptions();
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+
+ String originalOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ // Check there were some default dump options, we don't really need to
+ // know what they were just that there were some.
+ assertTrue("Expected some dump options after reset.", originalOptions.length > 0);
+
+ clearDumpOptions(); // This asserts that the options are empty.
+
+ try {
+ com.ibm.jvm.Dump.resetDumpOptions();
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+
+ String afterResetOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertEquals("Expected the same number of options setup before and after reset.",
+ originalOptions.length, afterResetOptions.length);
+ assertTrue("Expected contents of options to be equal before and after reset.",
+ Arrays.equals(originalOptions, afterResetOptions));
+ }
+
+ // testRoundTrip - reset options, query them, clear with -Xdump:none, pass back original strings to set, query and check we get back what we started with, reset and check again.
+ public void testRoundTrip() {
+ // Set the options back to the defaults.
+ clearDumpOptions();
+
+ try {
+ com.ibm.jvm.Dump.resetDumpOptions();
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+
+ String originalOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ // Check there were some default dump options, we don't really need to
+ // know what they were just that there were some.
+ assertTrue("Expected some dump options after reset.", originalOptions.length > 0);
+
+ clearDumpOptions(); // This asserts that the options are empty.
+
+ // Reset the options by resubmitting the result of queryDumpOptions
+ for (String agent : originalOptions) {
+ try {
+ com.ibm.jvm.Dump.setDumpOptions(agent);
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected to be able to set dump options to the strings returned by query dump options.");
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ }
+
+ String afterResetOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertEquals("Expected the same number of options setup before and after reset.",
+ originalOptions.length, afterResetOptions.length);
+ assertTrue("Expected contents of options to be equal before and after reset.",
+ Arrays.equals(originalOptions, afterResetOptions));
+ }
+
+ // testSet - set up a dump to trigger on some event, cause the event and check we have a dump
+ // testSetToolDump - confirm tool dumps are blocked, in several ways.
+ // public void testSetToolDump() {
+ // clearDumpOptions();
+ //
+ // String toolAgents[] = {"tool", "tool:events=gpf", "java+tool", "tool+java", "java+tool+heap",
+ // "tool+java:events=gpf", "java+tool:events=systhrow", "java+tool+heap:events=traceassert",
+ // " tool", "\ntool", "TOOL"};
+ //
+ // for( String agent: toolAgents ) {
+ // try {
+ // com.ibm.jvm.Dump.setDumpOptions(agent);
+ // fail("Did not expect to be able to set a tool dump agent, found: " + Arrays.toString(com.ibm.jvm.Dump.queryDumpOptions()));
+ // } catch (InvalidDumpOptionException e) {
+ // // Pass.
+ // // Check exception message.
+ // }
+ // // Check we didn't set things anyway.
+ // String newOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+ // assertTrue("Expected no options to be set.", newOptions.length == 0);
+ // }
+ // }
+
+ // testSetBadOptions - pass in garbage options.
+ public void testSetBadOptions() {
+ clearDumpOptions();
+
+ String badAgents[] = {
+ // "", // Empty String
+ "hippo", // Bad dump type
+ "java+hippo", // Bad second dump type
+ "java:hippo=gpf", // Bad dump option
+ "java:events=gpf,request=hippo", // Bad sub option
+ "java:events=gpf\nheap:events=systhrow", // Bad specification of two dumps
+ "java:events=hippo", // Bad event
+ "java:request=hippo", // Bad request
+ "java:priority=hippo", // Bad priority, should be a number
+ "defaults", // Setting defaults, not valid?
+ // "java:defaults:priority=500", // Setting defaults, not valid?
+ "help", // Not valid at runtime
+ "events", // Not valid at runtime
+ "request", // Not valid at runtime
+ "tokens", // Not valid at runtime
+ "nofailover", // Not valid at runtime - possibly should be!
+
+// Not valid, but not parsed yet. "java:events=vmstop,filter=hippo", // Bad filter (vmstop takes a number)
+// Not valid, not handled right.
+ "java:events=throw,filter=not/a/real/Exception", // Bad option, uses event that needs -Xdump:dynamic on the command line
+ "java:events=vmstart+throw,filter=not/a/real/Exception" // Bad option, uses event that needs -Xdump:dynamic on the command line
+
+// Valid "java:events=gpf,options=CLASSIC+PHD", // Options belonging to another dump type.
+// Valid "heap+java:events=gpf,opts=CLASSIC+PHD", // Options belonging to only one dump type.
+ };
+
+ try {
+ // System.err.println("Trying: null");
+ com.ibm.jvm.Dump.setDumpOptions(null);
+ fail("Did not expect to be able to set a bad dump agent, found: "
+ + Arrays.toString(com.ibm.jvm.Dump.queryDumpOptions()));
+ } catch (NullPointerException e) {
+ // Pass.
+ // Check exception message.
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected a null pointer exception");
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+
+ for (String agent : badAgents) {
+ try {
+ // System.err.println("Trying: " + agent);
+ com.ibm.jvm.Dump.setDumpOptions(agent);
+ com.ibm.jvm.Dump.setDumpOptions("what"); // We should not reach this so the output will be useful for debugging if we do.
+ fail("Did not expect to be able to set a bad dump option: " + agent + ", queryDumpOptions() found: "
+ + Arrays.toString(com.ibm.jvm.Dump.queryDumpOptions()));
+ } catch (InvalidDumpOptionException e) {
+ // Pass.
+ // Check exception message.
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ // Check we didn't set things anyway.
+ String newOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+ if (newOptions.length > 0) {
+ // System.err.println(Arrays.toString(newOptions));
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("what");
+ } catch (InvalidDumpOptionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ }
+ assertEquals("Expected no options to be set for agent string - " + agent, 0, newOptions.length);
+ }
+ }
+
+ // testSetDynamic - I don't think this should work at runtime.
+ public void testSetDynamic() {
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("dynamic");
+ fail("Did not expect to be able to set -Xdump:dynamic at runtime.");
+ } catch (InvalidDumpOptionException e) {
+ // Pass.
+ // Check exception message.
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ }
+
+ // testSetNullOptions - I don't think this should work at runtime.
+ public void testSetNullOptions() {
+ try {
+ com.ibm.jvm.Dump.setDumpOptions(null);
+ fail("Did not expect to be able to do setDumpOptions(null)");
+ } catch (NullPointerException e) {
+ // Pass.
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected NPE to be thrown not InvalidDumpOptionException");
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ }
+
+ // testSetDynamicOnly - This shouldn't work at runtime unless -Xdynamic was specified at startup.
+ public void testSetDynamicOnlyOptions() {
+ clearDumpOptions();
+
+ String[] dumpTypes = { "java", "system", "heap", "console", "stack", "silent", "jit" };
+ String[] dumpEvents = { "catch", "throw", "vmstart" }; // vmstart is not fixed with -Xdump:dynamic but it can't be set at runtime.
+ String[] dumpFilters = { "java/lang/OutOfMemoryError", "java/lang/NullPointerException", "made/up/Exception1",
+ "made/up/Exception2", "made/up/Exception3", "made/up/Exception4", "made/up/Exception5",
+ "made/up/Exception6", "made/up/Exception7" };
+
+ // None of these should work since uncaught and throw cannot be set at runtime unless -Xdump:dynamic was on the
+ // command line.
+ int count = 0;
+ for (String type : dumpTypes) {
+ for (String event : dumpEvents) {
+ for (String filter : dumpFilters) {
+ // Create agents the dump system can't merge.
+ String options = type + ":events=" + event + ",filter=" + filter + ",label=" + type + count++;
+ try {
+ com.ibm.jvm.Dump.setDumpOptions(options);
+ fail("Expected not to be ablel to set these dump options: " + options);
+ } catch (InvalidDumpOptionException e) {
+ // TODO Auto-generated catch block
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ }
+ }
+ }
+
+ String dumpAgents[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertNotNull("Expected array of dump agents returned, not null", dumpAgents);
+ assertEquals("Expected 0 dump agents configured found " + dumpAgents.length, 0, dumpAgents.length);
+
+ // Can probably have one function to validate two list of options match and re-use in lots of places.
+
+ int foundCount = checkDumpAgents(dumpTypes, dumpEvents, dumpFilters, dumpAgents);
+
+ assertEquals("Expected to find all the expected agents.", dumpAgents.length, foundCount);
+
+ clearDumpOptions();
+ }
+
+ /**
+ * Set the default options.
+ */
+ public void testSetDefaults() {
+ // Set the options back to the defaults.
+ clearDumpOptions(); // This asserts that the options are empty.
+
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("java:defaults:opts=HIPPO");
+ com.ibm.jvm.Dump.setDumpOptions("java");
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected setting the defaults to be a valid option.");
+ }
+
+ String afterDefaultsSetOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertEquals("Expected only one option to be setup.", 1, afterDefaultsSetOptions.length);
+
+ String option = afterDefaultsSetOptions[0];
+
+ assertTrue("Expected the option string to contain opts=HIPPO and java:",
+ option.startsWith("java:") && option.contains("opts=HIPPO"));
+ }
+
+ /**
+ * Set the default options and check that setting them hasn't affected
+ * the options we return to after reset.
+ */
+ public void testSetDefaultsAndReset() {
+ // Set the options back to the defaults.
+ clearDumpOptions();
+
+ try {
+ com.ibm.jvm.Dump.resetDumpOptions();
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+
+ String originalOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ // Check there were some default dump options, we don't really need to
+ // know what they were just that there were some.
+ assertTrue("Expected some dump options after reset.", originalOptions.length > 0);
+
+ clearDumpOptions(); // This asserts that the options are empty.
+
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("java:defaults:opts=HIPPO");
+ com.ibm.jvm.Dump.setDumpOptions("java");
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected setting the defaults to be a valid option.");
+ }
+
+ String afterDefaultsSetOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertEquals("Expected only one option to be setup.", 1, afterDefaultsSetOptions.length);
+
+ String option = afterDefaultsSetOptions[0];
+
+ assertTrue("Expected the option string to contain opts=HIPPO and java:",
+ option.startsWith("java:") && option.contains("opts=HIPPO"));
+
+ /* Now check reseting takes us back where it should do. */
+ try {
+ com.ibm.jvm.Dump.resetDumpOptions();
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+
+ String afterResetOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertEquals("Expected the same number of options setup before and after reset.",
+ originalOptions.length, afterResetOptions.length);
+ assertTrue("Expected contents of options to be equal before and after reset.",
+ Arrays.equals(originalOptions, afterResetOptions));
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISecurityTests.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISecurityTests.java
new file mode 100644
index 00000000000..c12bf1669a2
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISecurityTests.java
@@ -0,0 +1,627 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import static com.ibm.jvm.ras.tests.DumpAPISuite.deleteFile;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getFilesByPattern;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.isZOS;
+
+import static java.lang.Boolean.TRUE;
+import static java.lang.Boolean.FALSE;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import com.ibm.jvm.InvalidDumpOptionException;
+
+
+/**
+ * Tests of the dump API performed with a security manager set
+ * to block creation of files.
+ *
+ * No security manager is the default mode and covered by
+ * DumpAPIBasicTests
+ *
+ * *** Security is enabled by the ant script that normally runs these tests ***
+ *
+ * @author hhellyer
+ *
+ */
+public class DumpAPISecurityTests extends TestCase {
+
+ private long uid = System.currentTimeMillis();
+
+ // Record the files created by each testcase here so we can delete them
+ // later. Otherwise we will fill the disk up pretty quickly. While we check
+ // that the right kind of dump was created for each call we do any further
+ // validity checking on the dumps themselves. This test is just checking the
+ // API does what it should not that the dumps themselves are correct.
+ private Set fileNames;
+
+ @Override
+ protected void setUp() throws Exception {
+
+ uid = System.currentTimeMillis();
+
+ super.setUp();
+
+ fileNames = new HashSet();
+
+ // This isn't to free space, it's to trigger GC tracepoints so we don't get empty snap dumps!
+ System.gc();
+
+ // Make sure this is off for the start of every test.
+ System.clearProperty("com.ibm.jvm.enableLegacyDumpSecurity");
+ // And for the Trace.snap() tests.
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ for( String fileName: fileNames) {
+ deleteFile(fileName, this.getName());
+ }
+ }
+
+ private void addNewFilesToDelete(String[] beforeFileNames, String[] afterFileNames) {
+ for( String after : afterFileNames ) {
+ boolean newFile = true;
+ for( String before : beforeFileNames ) {
+ if( before.equals(after) ) {
+ newFile = false;
+ break;
+ }
+ }
+ if( newFile ) {
+ fileNames.add(after);
+ }
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testJavaDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.JavaDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * but not if the security permission should be listened to.
+ */
+ public void testJavaDumpNoArgsBlocked() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ System.clearProperty("com.ibm.jvm.enableLegacyDumpSecurity");
+
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ try {
+ com.ibm.jvm.Dump.JavaDump();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ //Pass
+ }
+
+ String[] afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ com.ibm.jvm.Dump.JavaDump();
+
+ afterFileNames = getFilesByPattern(userDir, javaCorePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ }
+
+ public void testJavaDumpWithFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "javacore."+ getName() + "." + uid + ".txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The javacore file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ try {
+ String javacoreName = com.ibm.jvm.Dump.javaDumpToFile(expectedName);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testJavaDumpNullFile() {
+ String userDir = System.getProperty("user.dir");
+ String javaCorePattern = "javacore\\..*\\.txt";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, javaCorePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(null);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a heap dump is generated from the standard com.ibm.jvm.Dump.HeapDump()
+ * call.
+ */
+ public void testHeapDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String heapdumpPattern = "heapdump\\..*\\.phd";
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, heapdumpPattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.HeapDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, heapdumpPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ public void testHeapDumpNoArgsBlocked() {
+ String userDir = System.getProperty("user.dir");
+ String heapdumpPattern = "heapdump\\..*\\.phd";
+
+ System.clearProperty("com.ibm.jvm.enableLegacyDumpSecurity");
+
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, heapdumpPattern);
+ int beforeCount = beforeFileNames.length;
+
+ try {
+ com.ibm.jvm.Dump.HeapDump();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ //Pass
+ }
+
+ String[] afterFileNames = getFilesByPattern(userDir, heapdumpPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ com.ibm.jvm.Dump.HeapDump();
+
+ afterFileNames = getFilesByPattern(userDir, heapdumpPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ }
+
+ public void testHeapDumpWithFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "heapdump."+ getName() + "." + uid + ".txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The heapdump file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ try {
+ String heapdumpName = com.ibm.jvm.Dump.heapDumpToFile(expectedName);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testHeapDumpNullFile() {
+ String userDir = System.getProperty("user.dir");
+ String heapdumpPattern = "heapdump\\..*\\.phd";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, heapdumpPattern);
+ int beforeCount = beforeFileNames.length;
+
+ String heapdumpName = null;
+ try {
+ heapdumpName = com.ibm.jvm.Dump.heapDumpToFile(null);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a heap dump is generated from the standard com.ibm.jvm.Dump.HeapDump()
+ * call.
+ */
+ public void testSnapDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String snapPattern = "Snap\\..*\\.trc";
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, snapPattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.SnapDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, snapPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ public void testSnapDumpNoArgsBlocked() {
+ String userDir = System.getProperty("user.dir");
+ String snapPattern = "Snap\\..*\\.trc";
+
+ System.clearProperty("com.ibm.jvm.enableLegacyDumpSecurity");
+
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, snapPattern);
+ int beforeCount = beforeFileNames.length;
+
+ try {
+ com.ibm.jvm.Dump.SnapDump();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ //Pass
+ }
+
+ String[] afterFileNames = getFilesByPattern(userDir, snapPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ com.ibm.jvm.Dump.SnapDump();
+
+ afterFileNames = getFilesByPattern(userDir, snapPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ }
+
+ /**
+ * Test a snap dump is generated from the standard com.ibm.jvm.Trace.snap()
+ * call.
+ * Done here rather than in the trace tests as this code knows how to delete
+ * a snap dump.
+ */
+ public void testTraceAPISnapDumpNoArgs() {
+ String userDir = System.getProperty("user.dir");
+ String snapPattern = "Snap\\..*\\.trc";
+
+ System.setProperty("com.ibm.jvm.enableLegacyTraceSecurity", FALSE.toString());
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, snapPattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Trace.snap();
+
+ String[] afterFileNames = getFilesByPattern(userDir, snapPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ /**
+ * Test a snap dump is blocked from the standard com.ibm.jvm.Trace.snap()
+ * call.
+ * Done here rather than in the trace tests as this code knows how to delete
+ * a snap dump.
+ */
+ public void testTraceAPISnapDumpNoArgsBlocked() {
+ String userDir = System.getProperty("user.dir");
+ String snapPattern = "Snap\\..*\\.trc";
+
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, snapPattern);
+ int beforeCount = beforeFileNames.length;
+
+ try {
+ com.ibm.jvm.Trace.snap();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ //Pass
+ }
+
+ String[] afterFileNames = getFilesByPattern(userDir, snapPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ com.ibm.jvm.Dump.SnapDump();
+
+ afterFileNames = getFilesByPattern(userDir, snapPattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ }
+
+ public void testSnapDumpWithFile() {
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "snap."+ getName() + "." + uid + ".trc";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The snap file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ try {
+ String snapName = com.ibm.jvm.Dump.snapDumpToFile(expectedName);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testSnapDumpNullFile() {
+ String userDir = System.getProperty("user.dir");
+ String snapPattern = "Snap\\..*\\.trc";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, snapPattern);
+ int beforeCount = beforeFileNames.length;
+
+ String snapName = null;
+ try {
+ snapName = com.ibm.jvm.Dump.snapDumpToFile(null);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a system dump is generated from the standard com.ibm.jvm.Dump.SystemDump()
+ * call.
+ */
+ public void testSystemDumpNoArgs() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ String userDir = System.getProperty("user.dir");
+ String corePattern = "core\\..*\\.dmp";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, corePattern);
+ int beforeCount = beforeFileNames.length;
+
+ com.ibm.jvm.Dump.SystemDump();
+
+ String[] afterFileNames = getFilesByPattern(userDir, corePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ public void testSystemDumpNoArgsBlocked() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+ String corePattern = "core\\..*\\.dmp";
+
+ System.clearProperty("com.ibm.jvm.enableLegacyDumpSecurity");
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, corePattern);
+ int beforeCount = beforeFileNames.length;
+
+ try {
+ com.ibm.jvm.Dump.SystemDump();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ //Pass
+ }
+
+ String[] afterFileNames = getFilesByPattern(userDir, corePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ int afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+
+ System.setProperty("com.ibm.jvm.enableLegacyDumpSecurity", FALSE.toString());
+
+ com.ibm.jvm.Dump.SystemDump();
+
+ afterFileNames = getFilesByPattern(userDir, corePattern);
+
+ addNewFilesToDelete(beforeFileNames, afterFileNames);
+
+ afterCount = afterFileNames.length;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+
+ }
+
+ public void testSystemDumpWithFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+
+ String expectedName = userDir + File.separator + "core."+ getName() + "." + uid + ".dmp";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ File expectedFile = new File(expectedName);
+ assertFalse("The core file " + expectedName + " already exists", expectedFile.exists());
+
+ // Check we got the correct name.
+ try {
+ String coreName = com.ibm.jvm.Dump.systemDumpToFile(expectedName);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ /**
+ * Test a java dump is generated from the standard com.ibm.jvm.Dump.JavaDump()
+ * call.
+ */
+ public void testSystemDumpNullFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+
+ String userDir = System.getProperty("user.dir");
+ String corePattern = "core\\..*\\.dmp";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, corePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String coreName = null;
+ try {
+ coreName = com.ibm.jvm.Dump.systemDumpToFile(null);
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+ public void testTriggerToolDump() {
+ try {
+ // The default options for tool dump may be invalid but we don't expect the dump
+ // to actually run.
+ com.ibm.jvm.Dump.triggerDump("tool");
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e ) {
+ // This is the success path!
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected security exception to be thrown not InvalidDumpOptionException.");
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISetTestXdumpdynamic.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISetTestXdumpdynamic.java
new file mode 100644
index 00000000000..d9a5d6ba365
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISetTestXdumpdynamic.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import java.util.Arrays;
+import java.io.*;
+
+import junit.framework.TestCase;
+
+import com.ibm.jvm.DumpConfigurationUnavailableException;
+import com.ibm.jvm.InvalidDumpOptionException;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getFilesByPattern;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.deleteFile;
+
+public class DumpAPISetTestXdumpdynamic extends TestCase {
+
+ private short MSG_FILTER_DUMP_COUNT = 2;
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ }
+
+ private void clearDumpOptions() {
+ String initialDumpOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+ try {
+ com.ibm.jvm.Dump.setDumpOptions("none");
+ } catch (InvalidDumpOptionException idoe ) {
+ idoe.printStackTrace();
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ } catch (DumpConfigurationUnavailableException e) {
+ e.printStackTrace();
+ }
+ String afterNoneOptions[] = com.ibm.jvm.Dump.queryDumpOptions();
+
+ assertTrue("Expected an empty array of dump options but got: " + Arrays.toString(afterNoneOptions), afterNoneOptions.length == 0);
+
+ }
+
+ // This shouldn't work at runtime unless -Xdynamic was specified at startup.
+ public void testSetDynamicOnlyOptions() {
+ clearDumpOptions();
+ String[] dumpTypes = {"java"};
+ String[] dumpEvents = {"catch", "throw", "uncaught", "systhrow"};
+ String[] dumpFilters = {"java/lang/OutOfMemoryError", "java/net/SocketException", "java/io/FileNotFoundException"};
+ String[] dumpMsgFilters = {"*JavaFVTTest*", "*JTC*"};
+
+ int count = 0;
+ for(String type: dumpTypes) {
+ for(String event: dumpEvents ) {
+ for(String filter: dumpFilters ) {
+ for(String msgFilter: dumpMsgFilters ) {
+ String options = type + ":events=" + event +",filter=" + filter + ",msg_filter=" + msgFilter+ ",label=" + type + count++;
+ try {
+ com.ibm.jvm.Dump.setDumpOptions(options);
+ } catch (InvalidDumpOptionException e) {
+ fail("Expected to be able to set these dump options: " + options);
+ } catch (DumpConfigurationUnavailableException e) {
+ fail("Dump configuration was unavailable.");
+ }
+ }
+ }
+ }
+ }
+
+ String dumpAgents[] = com.ibm.jvm.Dump.queryDumpOptions();
+ assertNotNull("Expected array of dump agents returned, not null", dumpAgents);
+ int noOfAgentsInstalled = dumpTypes.length * dumpEvents.length * dumpFilters.length * dumpMsgFilters.length;
+ assertEquals("Expected " + noOfAgentsInstalled + " dump agents configured found " + dumpAgents.length, noOfAgentsInstalled , dumpAgents.length);
+
+ /* Throws FileNotFoundException & Expects dumps from installed agents*/
+ String userDir = System.getProperty("user.dir");
+ String dumpFilePattern = "java[0-9]+";
+ /* Count the number of files before and after. Should increase by 2. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int beforeCount = beforeFileNames.length;
+ try {
+ FileInputStream fin = new FileInputStream("HelloJavaFVTTest.java");
+ fail("Expected FileNotFoundException");
+ } catch (FileNotFoundException fe) {
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int afterCount = afterFileNames.length;
+ int i = 0;
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + MSG_FILTER_DUMP_COUNT, afterCount);
+
+ /* delete the dump files */
+ if (afterCount > MSG_FILTER_DUMP_COUNT) {
+ int j = 0;
+ for (i = 0; i < afterCount; i++) {
+ for (String bfnames: beforeFileNames) {
+ if (bfnames.equals(afterFileNames[i])) {
+ afterFileNames[i] = null;
+ break;
+ }
+ }
+ if(afterFileNames[i] != null) {
+ afterFileNames[j++] = afterFileNames[i];
+ }
+ if(j == 2) {
+ break;
+ }
+ }
+ }
+ if (afterCount > 0) {
+ deleteFile(afterFileNames[0], this.getName());
+ deleteFile(afterFileNames[1], this.getName());
+ }
+ }
+ clearDumpOptions();
+ }
+
+}
\ No newline at end of file
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISuite.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISuite.java
new file mode 100644
index 00000000000..ead331a3d73
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPISuite.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import com.ibm.dtfj.image.Image;
+import com.ibm.dtfj.image.ImageFactory;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class DumpAPISuite {
+
+ public static enum DumpType {
+ SNAP_TYPE("snap"),
+ CONSOLE_TYPE("console"),
+ JAVA_TYPE("java"),
+ STACK_TYPE("stack"),
+ PHD_HEAP_TYPE("phd"),
+ CLASSIC_HEAP_TYPE("classic"),
+ SYSTEM_TYPE("system"),
+ FILE_NOT_FOUND(""),
+ READ_ERROR(""),
+ UNKNOWN("");
+
+ public final String name;
+
+ private DumpType(String name) {
+ this.name = name;
+ }
+
+ }
+
+ /* Common constants */
+ public static final String DUMP_TOOL_TYPE_ERR = "Tool dumps cannot be triggered via com.ibm.jvm.Dump API";
+ public static final String DUMP_ERROR_PARSING = "Error in dump options.";
+ public static final String DUMP_UNKNOWN_TYPE = "Error parsing dump options. Unknown dump type specified.";
+ public static final String DUMP_COULD_NOT_CREATE_FILE = DUMP_ERROR_PARSING;
+ public static final String DUMP_INVALID_OPTION = "Invalid dump option specified.";
+
+ /**
+ * This runs all the tests as a single suite.
+ * @return
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DumpAPISuite.class.getName());
+ //$JUnit-BEGIN$
+ suite.addTestSuite(DumpAPIBasicTests.class);
+ suite.addTestSuite(DumpAPITriggerTests.class);
+ suite.addTestSuite(DumpAPIQuerySetReset.class);
+ suite.addTestSuite(DumpAPITokensTests.class);
+ suite.addTestSuite(DumpAPISetTestXdumpdynamic.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+ // Deletes the named file, or prints an error message if it
+ // can't find it. On z/OS will check that a file doesn't exist
+ // in a dataset as well as on HFS. (Will check both for all files
+ // in case it has been copied onto HFS and exists in both locations.)
+ public static void deleteFile(String fileName, String testName) {
+ File toDelete = new File(fileName);
+ if( toDelete.exists() ) {
+ if(!toDelete.delete()) {
+ System.err.printf("Unable to delete file %s for test case %s will try to delete on exit.\n", fileName, testName);
+ toDelete.deleteOnExit();
+ } else {
+ //System.err.printf("Deleted file %s for test case %s\n", fileName, this.getName());
+ }
+
+ } else {
+ System.err.printf("Unable to find file %s to delete for test case %s\n", fileName, testName);
+ }
+ }
+
+ /* Some common functions for the whole suite. */
+ public static String[] getFilesByPattern(String dirName, final String pattern) {
+ File dir = new File(dirName);
+
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ if( name.matches(pattern) ) {
+ return true;
+ }
+ return false;
+ }
+ };
+ String[] fileNames = dir.list(filter);
+ return fileNames;
+ }
+
+ public static boolean isZOS() {
+ return "z/OS".equals(System.getProperty("os.name") );
+ }
+
+ /**
+ * Return the dump file type for the given file parameter.
+ * @param dumpFile
+ * @return a constant string representing the dump type.
+ */
+ public static DumpType getContentType(File dumpFile) {
+ // Hopefully we can usually do this by reading the first
+ // few bytes.
+ FileInputStream fileIn = null;
+ final byte[] portable_heap_dump;
+ try {
+ portable_heap_dump = "portable heap dump".getBytes("US-ASCII");
+ } catch (UnsupportedEncodingException e1) {
+ // US-ASCII really should be supported.
+ return DumpType.UNKNOWN;
+ }
+
+ try {
+ // Grab the first few bytes.
+ fileIn = new FileInputStream(dumpFile);
+ byte firstBytes[] = new byte[64];
+ int length = fileIn.read(firstBytes);
+
+ // Try various things we know will identify the different file types.
+ String initialString = new String(firstBytes);
+ if( (new String(firstBytes, "US-ASCII")).startsWith("UTTH") ) {
+ // Trace file header, trace file is binary UTTH will be in ASCII.
+ return DumpType.SNAP_TYPE;
+ } else if( initialString.startsWith("Thread=") ) {
+ // This is a console or stack dump, it depends how many threads!
+ StringBuffer contents = new StringBuffer((int)dumpFile.length());
+ contents.append(initialString);
+ byte[] buffer = new byte[1024];
+ int read = fileIn.read(buffer);
+ while( read > -1 ) {
+ contents.append(new String(buffer,0, read));
+ read = fileIn.read(buffer);
+ }
+ String[] threads = contents.toString().split("Thread=");
+
+ // We get an initial emptry array so we will have two
+ // elements for STACK and more for CONSOLE.
+ // (It is safe to assume the VM is running more than one thread.)
+ if( threads.length == 2) {
+ return DumpType.STACK_TYPE;
+ } else if (threads.length > 2) {
+ return DumpType.CONSOLE_TYPE;
+ }
+ } else if( initialString.startsWith("0SECTION TITLE")) {
+ return DumpType.JAVA_TYPE;
+ } else if( initialString.startsWith("// Version: ")) {
+ return DumpType.CLASSIC_HEAP_TYPE;
+ }
+ // Do the phd check by reading the first few bytes.
+ boolean phd = false;
+ for( int i = 2; i < length && i-2 < portable_heap_dump.length; i++ ) {
+ if( firstBytes[i] != portable_heap_dump[i-2] ) {
+ phd = false;
+ break;
+ } else {
+ phd = true;
+ }
+ }
+ if( phd ) {
+ return DumpType.PHD_HEAP_TYPE;
+ }
+
+ // Check for core dump. This needs to be last as the core readers can also
+ // open java dumps and heap dumps.
+ Image image = null;
+ try {
+ Class factoryClass = Class.forName("com.ibm.dtfj.image.j9.ImageFactory");
+ ImageFactory factory = (ImageFactory) factoryClass.newInstance();
+ image = factory.getImage(dumpFile);
+ if( image != null ) {
+ image.close();
+ return DumpType.SYSTEM_TYPE;
+ }
+ } catch (ClassNotFoundException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InstantiationException e) {
+ } finally {
+ if( image != null ) {
+ image.close();
+ }
+ }
+
+
+ } catch (FileNotFoundException e) {
+ // FILE_NOT_FOUND is expected for some tests.
+ return DumpType.FILE_NOT_FOUND;
+ } catch (IOException e) {
+ return DumpType.READ_ERROR;
+ } finally {
+ if( fileIn != null ) {
+ try {
+ fileIn.close();
+ } catch (IOException e) {
+ // Not able to fix this!
+ }
+ }
+ }
+
+ return DumpType.UNKNOWN;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPITokensTests.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPITokensTests.java
new file mode 100644
index 00000000000..88ff9c43531
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPITokensTests.java
@@ -0,0 +1,396 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import static com.ibm.jvm.ras.tests.DumpAPISuite.deleteFile;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getFilesByPattern;
+
+import java.io.File;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import com.ibm.jvm.InvalidDumpOptionException;
+
+/**
+ * This testcase checks that the dump tokens are correctly formatted into filenames.
+ * It only creates javacores rather than testing this for every dump type.
+ *
+ * The tokens are:
+ * %Y year 1900..????
+ * %y century 00..99
+ * %m month 01..12
+ * %d day 01..31
+ * %H hour 00..23
+ * %M minute 00..59
+ * %S second 00..59
+ *
+ * %pid process id
+ * %uid user name
+ * %seq dump counter
+ * %tick msec counter
+ * %home java home
+ * %last last dump
+ * %event dump event
+ *
+ * The date and time tokens are tested together.
+ * %home and %last are not tested as they contain paths
+ * and are only really intended for use with tool dumps.
+ *
+ * @author hhellyer
+ *
+ */
+public class DumpAPITokensTests extends TestCase {
+
+// private static String originalUserDir = System.getProperty("user.dir");
+
+ private long uid = System.currentTimeMillis();
+
+ // Record the files created by each testcase here so we can delete them
+ // later. Otherwise we will fill the disk up pretty quickly. While we check
+ // that the right kind of dump was created for each call we do any further
+ // validity checking on the dumps themselves. This test is just checking the
+ // API does what it should not that the dumps themselves are correct.
+ private Set fileNames;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ fileNames = new HashSet();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ for( String fileName: fileNames) {
+ deleteFile(fileName, this.getName());
+ }
+ }
+
+
+ public void testJavaDumpWithDateAndTimeTokens() {
+ String userDir = System.getProperty("user.dir");
+
+ // %Y year 1900..????
+ // %y century 00..99
+ // %m month 01..12
+ // %d day 01..31
+ // %H hour 00..23
+ // %M minute 00..59
+ // %S second 00..59
+ // These two patterns should correspond.
+ String dateFormatDump = "%Y%m%d%H%M%S";
+
+ String dateFormatJava = "yyyyMMddHHmmss";
+ SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatJava);
+
+
+ String dumpName = userDir + File.separator + "javacore."+ getName() + "." + dateFormatDump + "." + uid + ".txt";
+ String dumpFilePattern = ".*javacore\\."+ getName() + "\\.[0-9]+\\." + uid + "\\.txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", beforeFileNames.length == 0);
+
+ // Check we got the correct name.
+ long beforeTime = System.currentTimeMillis();
+ // The dump timestamp will round down to the nearest millsecond once
+ // parsed. Dumping may take less than a second so we need to make sure
+ // the timestamp will advance.
+ // (We aren't worried about millisecond precision in file timestamps just
+ // that it's actually filled out correctly.!)
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Do nothing.
+ }
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+ long afterTime = System.currentTimeMillis();
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", afterFileNames.length == 1);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+
+ // Check the filename returned matches the file we found searching the directory.
+ assertEquals("Expected created file to match returned filename", javacoreName, userDir + File.separator + afterFileNames[0]);
+
+ // Check the date formatted correctly and had the correct timestamp.
+ String javacoreDate = javacoreFile.getName().split("\\.")[2];
+ long javacoreTime = 0;
+ try {
+ // Parse it in the UTC timezone.
+ //System.err.println("Javacore date: " + javacoreDate);
+ javacoreTime = dateFormat.parse(javacoreDate).getTime();
+ } catch (ParseException e) {
+ fail("The timestamp in the filename was not in the expected format, timestamp was: " + javacoreDate + " format was: " + dateFormatJava);
+ }
+ //System.err.println("beforeTime = " + (new Date(beforeTime)) + " javacoreTime = " + (new Date(javacoreTime)) + " afterTime = " + (new Date(afterTime)));
+ //System.err.println("beforeTime = " + beforeTime + " javacoreTime = " + javacoreTime + " afterTime = " + afterTime);
+ assertTrue("The timestamp from the javacore was not between the timestamps taken before and after we took the dump.", javacoreTime >= beforeTime && afterTime >= javacoreTime );
+
+ }
+
+ public void testJavaDumpWithTickToken() {
+ String userDir = System.getProperty("user.dir");
+
+ // This will use the j9time_hires_clock() value.
+ // We can't assume it is in a particular unit or that it will be the same unit on different platforms.
+ String timeFormatDump = "%tick";
+
+ String dumpName = userDir + File.separator + "javacore."+ getName() + "." + timeFormatDump + "." + uid + ".txt";
+ String dumpFilePattern = ".*javacore\\."+ getName() + "\\.[0-9]+\\." + uid + "\\.txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", beforeFileNames.length == 0);
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", afterFileNames.length == 1);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+
+ // Check the filename returned matches the file we found searching the directory.
+ assertEquals("Expected created file to match returned filename", javacoreName, userDir + File.separator + afterFileNames[0]);
+
+ // We've checked we got a file named correctly, and that the file really was created.
+ // Cannot check the absolute value of the time stamp as its just the hires time counter.
+ }
+
+ public void testJavaDumpWithPidToken() {
+ String userDir = System.getProperty("user.dir");
+
+ String dumpToken = "%pid";
+
+ String dumpName = userDir + File.separator + "javacore."+ getName() + "." + dumpToken + "." + uid + ".txt";
+ String dumpFilePattern = ".*javacore\\."+ getName() + "\\.[0-9]+\\." + uid + "\\.txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", beforeFileNames.length == 0);
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", afterFileNames.length == 1);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+
+ // Check the filename returned matches the file we found searching the directory.
+ assertEquals("Expected created file to match returned filename", javacoreName, userDir + File.separator + afterFileNames[0]);
+
+ }
+
+ /* This test fails as there isn't a mapping to a friendly name for
+ * J9RAS_DUMP_ON_USER_REQUEST. We could fix that, until then this
+ * test will fail.
+ */
+ public void testJavaDumpWithEventToken() {
+ String userDir = System.getProperty("user.dir");
+
+ String dumpToken = "%event";
+
+ String dumpName = userDir + File.separator + "javacore."+ getName() + "." + dumpToken + "." + uid + ".txt";
+ String dumpFilePattern = ".*javacore\\."+ getName() + "\\.api." + uid + "\\.txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", beforeFileNames.length == 0);
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertEquals("Found a file matching our output pattern before taking the dump.", 1, afterFileNames.length);
+
+
+
+ // Check the filename returned matches the file we found searching the directory.
+ assertEquals("Expected created file to match returned filename", javacoreName, userDir + File.separator + afterFileNames[0]);
+
+ }
+
+ public void testJavaDumpWithUidToken() {
+ String userDir = System.getProperty("user.dir");
+
+ // This will use the j9time_hires_clock() value.
+ // We can't assume it is in a particular unit or that it will be the same unit on different platforms.
+ String dumpToken = "%uid";
+ String javaUserid = System.getProperty("user.name");
+
+ String dumpName = userDir + File.separator + "javacore."+ getName() + "." + dumpToken + "." + uid + ".txt";
+ String dumpFilePattern = ".*javacore\\."+ getName() + "\\." + javaUserid + "\\." + uid + "\\.txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", beforeFileNames.length == 0);
+
+ String javacoreName = null;
+ try {
+ javacoreName = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName);
+ fileNames.add(javacoreName);
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", afterFileNames.length == 1);
+
+ // Check it really exists.
+ File javacoreFile = new File(javacoreName);
+ assertTrue("Failed to find files " + javacoreName + " after requesting " + javacoreName, javacoreFile.exists());
+
+
+ // Check the filename returned matches the file we found searching the directory.
+ assertEquals("Expected created file to match returned filename", javacoreName, userDir + File.separator + afterFileNames[0]);
+
+ }
+
+ public void testJavaDumpWithSequenceToken() {
+ String userDir = System.getProperty("user.dir");
+
+ String dumpToken = "%seq";
+
+ String dumpName = userDir + File.separator + "javacore."+ getName() + "." + dumpToken + "." + uid + ".txt";
+ String dumpFilePattern = ".*javacore\\."+ getName() + "\\.[0-9]+\\." + uid + "\\.txt";
+
+ // Check the file doesn't exist, otherwise the dump code moves it.
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", beforeFileNames.length == 0);
+
+ String javacoreName1 = null;
+ try {
+ javacoreName1 = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName1);
+ fileNames.add(javacoreName1);
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ assertTrue("Found a file matching our output pattern before taking the dump.", afterFileNames.length == 1);
+
+ // Check it really exists.
+ File javacoreFile1 = new File(javacoreName1);
+ assertTrue("Failed to find files " + javacoreName1 + " after requesting " + javacoreName1, javacoreFile1.exists());
+
+
+ // Check the filename returned matches the file we found searching the directory.
+ assertEquals("Expected created file to match returned filename", javacoreName1, userDir + File.separator + afterFileNames[0]);
+
+ // Check the date formatted correctly and had the correct timestamp.
+ String seq1Str = javacoreFile1.getName().split("\\.")[2];
+
+ // Create a second javacore, to see if %seq has incremented.
+ String javacoreName2 = null;
+ try {
+ javacoreName2 = com.ibm.jvm.Dump.javaDumpToFile(dumpName);
+ } catch (InvalidDumpOptionException e ) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+ assertNotNull("Expected javacore filename to be returned, not null", javacoreName2);
+ fileNames.add(javacoreName2);
+
+ // Check it really exists.
+ File javacoreFile2 = new File(javacoreName2);
+ assertTrue("Failed to find files " + javacoreName2 + " after requesting " + javacoreName1, javacoreFile2.exists());
+
+ String seq2Str = javacoreFile2.getName().split("\\.")[2];
+
+ int seq1 = Integer.valueOf(seq1Str);
+ int seq2 = Integer.valueOf(seq2Str);
+
+ assertTrue("Expected sequence number to increment by one, but seq1 = " + seq1 + " seq2 = " + seq2, seq1 + 1 == seq2);
+
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIToolSecuritySuite.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIToolSecuritySuite.java
new file mode 100644
index 00000000000..555e98f357b
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPIToolSecuritySuite.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * A simple test suite to let us re-test that tool dumps are blocked
+ * when DumpPermission is granted but ToolDumpPermission is not.
+ * Also checks that a normal dump works.
+ *
+ * @author hhellyer
+ *
+ */
+public class DumpAPIToolSecuritySuite {
+ /**
+ * This runs all the tests as a single suite.
+ * @return
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DumpAPIToolSecuritySuite.class.getName());
+ //$JUnit-BEGIN$
+ suite.addTest(TestSuite.createTest(DumpAPISecurityTests.class, "testTriggerToolDump"));
+ suite.addTest(TestSuite.createTest(DumpAPIBasicTests.class, "testJavaDumpWithFile"));
+ //$JUnit-END$
+ return suite;
+ }
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPITriggerTests.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPITriggerTests.java
new file mode 100644
index 00000000000..3127e929989
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/DumpAPITriggerTests.java
@@ -0,0 +1,375 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import static com.ibm.jvm.ras.tests.DumpAPISuite.DUMP_COULD_NOT_CREATE_FILE;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.DUMP_ERROR_PARSING;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.deleteFile;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getContentType;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.getFilesByPattern;
+import static com.ibm.jvm.ras.tests.DumpAPISuite.isZOS;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import com.ibm.jvm.InvalidDumpOptionException;
+import com.ibm.jvm.ras.tests.DumpAPISuite.DumpType;
+
+public class DumpAPITriggerTests extends TestCase {
+
+ private long uid = System.currentTimeMillis();
+
+ // Record the files created by each testcase here so we can delete them
+ // later. Otherwise we will fill the disk up pretty quickly. While we check
+ // that the right kind of dump was created for each call we do any further
+ // validity checking on the dumps themselves. This test is just checking the
+ // API does what it should not that the dumps themselves are correct.
+ private Set fileNames;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ fileNames = new HashSet();
+
+ // This isn't to free space, it's to trigger GC tracepoints so we don't get empty snap dumps!
+ System.gc();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ for( String fileName: fileNames) {
+ deleteFile(fileName, this.getName());
+ }
+ }
+
+ public void testTriggerDumpNullOpts() {
+ try {
+ doTestTriggerBadDumpX(null);
+ fail("Expected NPE to be thrown.");
+ } catch( NullPointerException npe ) {
+ // pass
+ }
+ }
+
+ public void testTriggerDumpEmptyOpts() {
+ doTestTriggerBadDumpX("");
+ }
+
+ public void testTriggerDumpJavaNoOpts() {
+ doTestTriggerDumpNoOpts("java", DumpType.JAVA_TYPE);
+ }
+
+ public void testTriggerDumpSystemNoOpts() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+ doTestTriggerDumpNoOpts("system", DumpType.SYSTEM_TYPE);
+ }
+
+ public void testTriggerDumpHeapNoOpts() {
+ doTestTriggerDumpNoOpts("heap", DumpType.PHD_HEAP_TYPE);
+ }
+
+ public void testTriggerDumpSnapNoOpts() {
+ doTestTriggerDumpNoOpts("snap", DumpType.SNAP_TYPE);
+ }
+
+// Don't test this, the default dump agent runs the debugger and connects back to this process.
+// It's a great way to hang the test cases.
+// public void testTriggerDumpToolNoOpts() {
+// doTestTriggerDumpNoOpts("snap", DumpType.TOOL_TYPE);
+// }
+
+ public void testTriggerDumpConsoleNoOpts() {
+ // Default console dump goes to stderr therefore no file will be found.
+ doTestTriggerDumpNoOpts("console", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpStackNoOpts() {
+ // Default stack dump goes to stderr therefore no file will be found.
+ doTestTriggerDumpNoOpts("stack", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpSilentNoOpts() {
+ doTestTriggerDumpNoOpts("silent", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpBadAgentNoOpts() {
+ // The chances of us adding a new dump type called walrus in the future are small.
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("walrus");
+ assertEquals("Incorrect message triggering tool dump.", DUMP_ERROR_PARSING, e.getMessage());
+ }
+
+ public void testTriggerDumpJavaToFile() {
+ doTestTriggerDumpWithFile("java", "javacore." + getName() + "." + uid + ".txt", DumpType.JAVA_TYPE);
+ }
+
+ public void testTriggerDumpSystemToFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+ doTestTriggerDumpWithFile("system", "system." + getName() + "." + uid + ".dmp", DumpType.SYSTEM_TYPE);
+ }
+
+ public void testTriggerDumpHeapToFile() {
+ doTestTriggerDumpWithFile("heap", "heap." + getName() + "." + uid + ".phd", DumpType.PHD_HEAP_TYPE);
+ }
+
+ public void testTriggerDumpClassicHeapToFile() {
+ String fileName = "heap." + getName() + "." + uid + ".txt";
+ String type = "heap";
+ File dumpFile = new File(fileName);
+ assertFalse("Found file " + fileName + " before requesting " + fileName, dumpFile.exists());
+ doTestTriggerDumpX(type +":file=" + fileName + ",opts=CLASSIC", DumpType.CLASSIC_HEAP_TYPE);
+ assertTrue("Failed to find file " + fileName + " after requesting " + fileName, dumpFile.exists());
+ }
+
+
+ public void testTriggerDumpSnapToFile() {
+ doTestTriggerDumpWithFile("snap", "snap." + getName() + "." + uid + ".trc", DumpType.SNAP_TYPE);
+ }
+
+ public void testTriggerDumpTool() {
+ // This will be slightly broken as no file will be created but as we don't get the return code
+ // from the command we just want to check the string is accepted and we attempt to run something.
+ doTestTriggerDumpX("tool:exec=tool." + getName() + "." + uid + ".txt", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpConsoleToFile() {
+ doTestTriggerDumpWithFile("console", "console." + getName() + "." + uid + ".txt", DumpType.CONSOLE_TYPE);
+ }
+
+ public void testTriggerDumpStackToFile() {
+ doTestTriggerDumpWithFile("stack", "stack." + getName() + "." + uid + ".txt", DumpType.STACK_TYPE);
+ }
+
+ public void testTriggerDumpSilentToFile() {
+ doTestTriggerDumpWithFile("silent", "silent." + getName() + "." + uid + ".txt", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpBadAgentToFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("walrus:label=walrus." + getName() + "." + uid + ".txt");
+ assertEquals("Incorrect message triggering tool dump.", DUMP_ERROR_PARSING, e.getMessage());
+ }
+
+ public void testTriggerDumpJavaNoFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("java:file=");
+ assertEquals("Incorrect message triggering java dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpSystemNoFile() {
+ if( isZOS() ) {
+ System.err.printf("Skipping %s, z/OS system dumps currently inaccessable in Java 8, see CMVC 193090\n", this.getName());
+ return;
+ }
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("system:label=");
+ assertEquals("Incorrect message triggering system dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpHeapNoFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("heap:file=");
+ assertEquals("Incorrect message triggering heap dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpSnapNoFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("snap:file=");
+ assertEquals("Incorrect message triggering snap dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpConsoleNoFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("console:file=");
+ assertEquals("Incorrect message triggering console dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpStackNoFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("stack:file=");
+ assertEquals("Incorrect message triggering java dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpJavaBadFile() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("java:file=..");
+ assertEquals("Incorrect message triggering java dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpJavaToDirectory() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("java:file=javaDump" + File.separator);
+ assertEquals("Incorrect message triggering java dump with missing file.", DUMP_COULD_NOT_CREATE_FILE, e.getMessage());
+ }
+
+ public void testTriggerDumpConsoleDashFile() {
+ doTestTriggerDumpWithFile("console", "-", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpStackDashFile() {
+ doTestTriggerDumpWithFile("stack", "-", DumpType.FILE_NOT_FOUND);
+ }
+
+ public void testTriggerDumpJavaDashFile() {
+ doSTDOUTTestTriggerDumpX("java:file=-");
+ }
+
+ public void testTriggerMultipleDumpsNoOpts() {
+ InvalidDumpOptionException e = doTestTriggerBadDumpX("java+heap");
+ assertEquals("Incorrect message triggering java dump with missing file.", DUMP_ERROR_PARSING, e.getMessage());
+ }
+
+ /* JIT dumps currently do nothing. */
+ /*public void testTriggerDumpJit() {
+ doTestTriggerDump("jit");
+ }*/
+
+ public void doTestTriggerDumpNoOpts(String type, DumpType expectedType) {
+ doTestTriggerDumpX(type, expectedType);
+ }
+
+
+ /**
+ * Triggers a dump to a specific file name and checks it exists.
+ * Assumes that the filename does not contain wild cards.
+ * @param type
+ * @param fileName
+ */
+ public void doTestTriggerDumpWithFile(String type, String fileName, DumpType expectedType) {
+ File dumpFile = new File(fileName);
+ assertFalse("Found file " + fileName + " before requesting " + fileName, dumpFile.exists());
+ doTestTriggerDumpX(type +":label=" + fileName, expectedType);
+ }
+
+ /**
+ * Triggers a dump with the given options and does basic checking
+ * for files created and created with the right name.
+ * @param options
+ */
+ public void doTestTriggerDumpX(String options, DumpType expectedType) {
+ String userDir = System.getProperty("user.dir");
+ String dumpFilePattern = ".*\\.*";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String fileName = null;
+ try {
+ fileName = com.ibm.jvm.Dump.triggerDump(options);
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ fail("Exception thrown by triggerDump(" + options +")");
+ } catch (InvalidDumpOptionException e) {
+ e.printStackTrace();
+ fail("Exception thrown by triggerDump(" + options +")");
+ }
+ //System.err.println("Dump file name is: " + fileName);
+ assertNotNull("Expected triggerDump to return file name, not null", fileName);
+
+ // Check the generated file really exists, unless we wrote to stderr or don't expect to find a file!
+ File dumpFile = new File(fileName);
+ if( !"-".equals(fileName) && expectedType != DumpType.FILE_NOT_FOUND ) {
+ assertTrue("Failed to find files " + fileName + " after requesting " + fileName, dumpFile.exists());
+ fileNames.add(fileName);
+ }
+ // Check content
+ DumpType type = getContentType(dumpFile);
+ assertEquals("Expected file " + dumpFile + " to contain a dump of type " + expectedType.name + " but content type was: " + type.name, expectedType, type);
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int afterCount = afterFileNames.length;
+ if( "-".equals(fileName) || expectedType == DumpType.FILE_NOT_FOUND ) {
+ // Wrote to stderr, or no file expected so no more files.
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+ } else {
+ // Wrote to filename, one more file.
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount + 1, afterCount);
+ }
+
+ }
+
+ public void doSTDOUTTestTriggerDumpX(String options) {
+ String userDir = System.getProperty("user.dir");
+ String dumpFilePattern = ".*\\.*";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String fileName = null;
+
+ try {
+ fileName = com.ibm.jvm.Dump.triggerDump(options);
+ assertEquals("Expected fileName /STDOUT/, but fileName was " + fileName, "/STDOUT/", fileName);
+ } catch (InvalidDumpOptionException e) {
+ e.printStackTrace();
+ fail("Unexpected InvalidDumpOption exception thrown.");
+ }
+
+ // Check the number of files has not increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int afterCount = afterFileNames.length;
+ // Should have failed to create a dump, so no more files should be created.
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+ }
+
+ /**
+ * Triggers a dump with the given options, which are incorrect,
+ * and checks no files are created.
+ * @param options
+ * @return the exception that was thrown so the caller can verify it was the correct one.
+ */
+ public InvalidDumpOptionException doTestTriggerBadDumpX(String options) {
+ String userDir = System.getProperty("user.dir");
+ String dumpFilePattern = ".*\\.*";
+
+ /* Count the number of files before and after. Should increase by one. */
+ String[] beforeFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int beforeCount = beforeFileNames.length;
+
+ String fileName = null;
+ InvalidDumpOptionException exception = null;
+
+ /* We are checking these options cause an error, so the InvalidDumpOptionException path is the good case. */
+ try {
+ fileName = com.ibm.jvm.Dump.triggerDump(options);
+ fail("Exception not thrown by triggerDump(" + options +"), fileName returned was: " + fileName);
+ } catch (SecurityException e) {
+ fail("Security exception thrown by triggerDump(" + options +")");
+ } catch (InvalidDumpOptionException e) {
+ exception = e;
+ }
+ assertNull("Expected triggerDump not to return null file name", fileName);
+
+ // Check the number of files has increased. (We weren't returned a filename that already existed.)
+ String[] afterFileNames = getFilesByPattern(userDir, dumpFilePattern);
+ int afterCount = afterFileNames.length;
+ // Should have failed to create a dump, so no more files should be created.
+ assertEquals("Failed to find expected number of files in " + userDir + " , found:" + Arrays.toString(afterFileNames), beforeCount, afterCount);
+ return exception;
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/LogAPISecurityTests.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/LogAPISecurityTests.java
new file mode 100644
index 00000000000..53c524f829e
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/LogAPISecurityTests.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import static java.lang.Boolean.TRUE;
+import static java.lang.Boolean.FALSE;
+import junit.framework.TestCase;
+
+public class LogAPISecurityTests extends TestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Make sure this is off for the start of every test.
+ System.clearProperty("com.ibm.jvm.enableLegacyLogSecurity");
+ }
+
+ public void testQueryLogOptions() {
+ System.setProperty("com.ibm.jvm.enableLegacyLogSecurity", FALSE.toString());
+ com.ibm.jvm.Log.QueryOptions();
+
+ }
+
+ public void testQueryLogOptionsBlocked() {
+ System.clearProperty("com.ibm.jvm.enableLegacyLogSecurity");
+ try {
+ com.ibm.jvm.Log.QueryOptions();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ //Pass
+ }
+
+
+
+ }
+
+ public void testSetLogOptions() {
+ System.setProperty("com.ibm.jvm.enableLegacyLogSecurity", FALSE.toString());
+ /* Set to the default options so we don't really change things for other tests. */
+ com.ibm.jvm.Log.SetOptions("error,vital");
+
+ }
+
+ public void testSetLogOptionsBlocked() {
+ System.clearProperty("com.ibm.jvm.enableLegacyLogSecurity");
+ try {
+ /* Set to the default options so we don't really change things for other tests. */
+ com.ibm.jvm.Log.SetOptions("error,vital");
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ // Pass
+ }
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/TraceAPISecurityTests.java b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/TraceAPISecurityTests.java
new file mode 100644
index 00000000000..4903fe29f42
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/jvm/ras/tests/TraceAPISecurityTests.java
@@ -0,0 +1,742 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.jvm.ras.tests;
+
+import static java.lang.Boolean.TRUE;
+import static java.lang.Boolean.FALSE;
+import junit.framework.TestCase;
+import com.ibm.jvm.Trace;
+
+public class TraceAPISecurityTests extends TestCase {
+
+ static final String[] TEMPLATES = new String[54];
+ static {
+ TEMPLATES[0] = Trace.EVENT;
+ TEMPLATES[1] = Trace.EVENT + "Tracepoint #1 ";
+ TEMPLATES[2] = Trace.EVENT + "Tracepoint #2 insert1=%s";
+ TEMPLATES[3] = Trace.EVENT + "Tracepoint #3 insert1=%s insert2=%s";
+ TEMPLATES[4] = Trace.EVENT + "Tracepoint #4 insert1=%s insert2=%s insert3=%s";
+ TEMPLATES[5] = Trace.EVENT + "Tracepoint #5 insert1=%s insert2=%p";
+ TEMPLATES[6] = Trace.EVENT + "Tracepoint #6 insert1=%p insert2=%s";
+ TEMPLATES[7] = Trace.EVENT + "Tracepoint #7 insert1=%s insert2=%d";
+ TEMPLATES[8] = Trace.EVENT + "Tracepoint #8 insert1=%d insert2=%s";
+ TEMPLATES[9] = Trace.EVENT + "Tracepoint #9 insert1=%s insert2=%lld";
+ TEMPLATES[10] = Trace.EVENT + "Tracepoint #10 insert1=%lld insert2=%s"; // mkomine@77003
+ TEMPLATES[11] = Trace.EVENT + "Tracepoint #11 insert1=%s insert2=%d";
+ TEMPLATES[12] = Trace.EVENT + "Tracepoint #12 insert1=%d insert2=%s";
+ TEMPLATES[13] = Trace.EVENT + "Tracepoint #13 insert1=%s insert2=%c";
+ TEMPLATES[14] = Trace.EVENT + "Tracepoint #14 insert1=%c insert2=%s";
+ TEMPLATES[15] = Trace.EVENT + "Tracepoint #15 insert1=%s insert2=%f";
+ TEMPLATES[16] = Trace.EVENT + "Tracepoint #16 insert1=%e insert2=%s";
+ TEMPLATES[17] = Trace.EVENT + "Tracepoint #17 insert1=%s insert2=%e";
+ TEMPLATES[18] = Trace.EVENT + "Tracepoint #18 insert1=%e insert2=%s";
+ TEMPLATES[19] = Trace.EVENT + "Tracepoint #19 insert1=%p";
+ TEMPLATES[20] = Trace.EVENT + "Tracepoint #20 insert1=%p insert2=%p";
+ TEMPLATES[21] = Trace.EVENT + "Tracepoint #21 insert1=%d";
+ TEMPLATES[22] = Trace.EVENT + "Tracepoint #22 insert1=%d insert2=%d";
+ TEMPLATES[23] = Trace.EVENT + "Tracepoint #23 insert1=%d insert2=%d insert3=%d";
+ TEMPLATES[24] = Trace.EVENT + "Tracepoint #24 insert1=%lld";
+ TEMPLATES[25] = Trace.EVENT + "Tracepoint #25 insert1=%lld insert2=%lld";
+ TEMPLATES[26] = Trace.EVENT + "Tracepoint #26 insert1=%lld insert2=%lld insert3=%lld";
+ TEMPLATES[27] = Trace.EVENT + "Tracepoint #27 insert1=%d";
+ TEMPLATES[28] = Trace.EVENT + "Tracepoint #28 insert1=%d insert2=%d";
+ TEMPLATES[29] = Trace.EVENT + "Tracepoint #29 insert1=%d insert2=%d insert3=%d";
+ TEMPLATES[30] = Trace.EVENT + "Tracepoint #30 insert1=%c";
+ TEMPLATES[31] = Trace.EVENT + "Tracepoint #31 insert1=%c insert2=%c";
+ TEMPLATES[32] = Trace.EVENT + "Tracepoint #32 insert1=%c insert2=%c insert3=%c";
+ TEMPLATES[33] = Trace.EVENT + "Tracepoint #33 insert1=%f";
+ TEMPLATES[34] = Trace.EVENT + "Tracepoint #34 insert1=%e insert2=%e";
+ TEMPLATES[35] = Trace.EVENT + "Tracepoint #35 insert1=%f insert2=%f insert3=%f";
+ TEMPLATES[36] = Trace.EVENT + "Tracepoint #36 insert1=%d";
+ TEMPLATES[37] = Trace.EVENT + "Tracepoint #37 insert1=%d insert2=%d";
+ TEMPLATES[38] = Trace.EVENT + "Tracepoint #38 insert1=%f insert2=%f insert3=%f";
+ TEMPLATES[39] = Trace.EVENT + "Tracepoint #39 insert1=%s insert2=%p insert3=%s";
+ TEMPLATES[40] = Trace.EVENT + "Tracepoint #40 insert1=%p insert2=%s insert3=%p";
+ TEMPLATES[41] = Trace.EVENT + "Tracepoint #41 insert1=%s insert2=%d insert3=%s";
+ TEMPLATES[42] = Trace.EVENT + "Tracepoint #42 insert1=%d insert2=%s insert3=%d";
+ TEMPLATES[43] = Trace.EVENT + "Tracepoint #43 insert1=%s insert2=%lld insert3=%s";
+ TEMPLATES[44] = Trace.EVENT + "Tracepoint #44 insert1=%lld insert2=%s insert3=%lld";
+ TEMPLATES[45] = Trace.EVENT + "Tracepoint #45 insert1=%s insert2=%d insert3=%s";
+ TEMPLATES[46] = Trace.EVENT + "Tracepoint #46 insert1=%d insert2=%s insert3=%d";
+ TEMPLATES[47] = Trace.EVENT + "Tracepoint #47 insert1=%s insert2=%c insert3=%s";
+ TEMPLATES[48] = Trace.EVENT + "Tracepoint #48 insert1=%c insert2=%s insert3=%c";
+ TEMPLATES[49] = Trace.EVENT + "Tracepoint #49 insert1=%s insert2=%f insert3=%s";
+ TEMPLATES[50] = Trace.EVENT + "Tracepoint #50 insert1=%f insert2=%s insert3=%f";
+ TEMPLATES[51] = Trace.EVENT + "Tracepoint #51 insert1=%s insert2=%d insert3=%s";
+ TEMPLATES[52] = Trace.EVENT + "Tracepoint #52 insert1=%d insert2=%s insert3=%d";
+ TEMPLATES[53] = Trace.EVENT + "Tracepoint #53 TEST PASSED";
+ }
+
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Make sure this is off for the start of every test.
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+ }
+
+ public void testGetMicros() {
+
+ System.setProperty("com.ibm.jvm.enableLegacyTraceSecurity", FALSE.toString());
+ com.ibm.jvm.Trace.getMicros();
+
+ }
+
+ public void testQueryGetMicrosNotBlocked() {
+ System.setProperty("com.ibm.jvm.enableLegacyLogSecurity", FALSE.toString());
+
+ try {
+ com.ibm.jvm.Log.QueryOptions();
+ } catch (SecurityException e) {
+ // Fail, this method shouldn't have security enabled.
+ fail("Expected security exception to be thrown.");
+ }
+ }
+
+ public void testSuspendResumeNotBlocked() {
+ System.setProperty("com.ibm.jvm.enableLegacyTraceSecurity", FALSE.toString());
+ com.ibm.jvm.Trace.suspend();
+ com.ibm.jvm.Trace.resume();
+ }
+
+ public void testSuspendResumeBlocked() {
+
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+
+ try {
+ /* Disable global trace */
+ com.ibm.jvm.Trace.suspend();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ // Pass
+ }
+ try {
+ /* Enable global trace */
+ com.ibm.jvm.Trace.resume();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ // Pass
+ }
+ }
+
+ public void testSuspendThisResumeThisNotBlocked() {
+ System.setProperty("com.ibm.jvm.enableLegacyTraceSecurity", FALSE.toString());
+ com.ibm.jvm.Trace.suspendThis();
+ com.ibm.jvm.Trace.resumeThis();
+
+ }
+
+ public void testSuspendThisResumeThisBlocked() {
+
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+
+ try {
+ /* Set to the default options so we don't really change things for other tests. */
+ com.ibm.jvm.Trace.suspendThis();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ // Pass
+ }
+ try {
+ /* Set to the default options so we don't really change things for other tests. */
+ com.ibm.jvm.Trace.resumeThis();
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ // Pass
+ }
+ }
+
+ public void testSetNotBlocked() {
+ System.setProperty("com.ibm.jvm.enableLegacyTraceSecurity", FALSE.toString());
+ int result = com.ibm.jvm.Trace.set("maximal=j9trc.0");
+ assertEquals("Expected to be able to set tracepoint", 0, result);
+ }
+
+ public void testSetBlocked() {
+
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+
+ try {
+ /* Set the trace init tracepoint, will already be set and won't ever fire after
+ * the trace library comes up anyway.
+ */
+ com.ibm.jvm.Trace.set("maximal=j9trc.0");
+ fail("Expected security exception to be thrown.");
+ } catch (SecurityException e) {
+ // Pass
+ }
+ }
+
+ /**
+ * Re-run the trace point taking tests from TestTraceArguments to confirm
+ * that they aren't blocked by default when security is enabled.
+ */
+ public void testApplicationTraceNotBlocked() {
+ Object anyOldObject = new java.lang.Thread();
+ Object anotherOldObject = new java.lang.Thread();
+ System.setProperty("com.ibm.jvm.enableLegacyTraceSecurity", FALSE.toString());
+
+ int componentId = Trace.registerApplication("TestTraceArguments",TEMPLATES);
+
+ Trace.set("maximal=TestTraceArguments");
+
+ // Tests for all the different Trace.trace() methods
+
+ // public static void trace(int, int)
+ Trace.trace(componentId,0);
+ // public static void trace(int, int)
+ Trace.trace(componentId,1);
+ // public static void trace(int, int, java.lang.String)
+ Trace.trace(componentId,2,"hello");
+ // public static void trace(int, int, java.lang.String, java.lang.String)
+ Trace.trace(componentId,3,"hello1","hello2");
+ // public static void trace(int, int, java.lang.String, java.lang.String, java.lang.String)
+ Trace.trace(componentId,4,"hello1","hello2","hello3");
+ // public static void trace(int, int, java.lang.String, java.lang.Object)
+ Trace.trace(componentId,5,"hello",anyOldObject);
+ // public static void trace(int, int, java.lang.Object, java.lang.String)
+ Trace.trace(componentId,6,anyOldObject,"hello");
+ // public static void trace(int, int, java.lang.String, int)
+ Trace.trace(componentId,7,"hello",9);
+ // public static void trace(int, int, int, java.lang.String)
+ Trace.trace(componentId,8,9,"hello");
+ // public static void trace(int, int, java.lang.String, long)
+ Trace.trace(componentId,9,"hello",9L);
+ // public static void trace(int, int, long, java.lang.String)
+ Trace.trace(componentId,10,Long.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.String, byte)
+ Trace.trace(componentId,11,"hello",Byte.MAX_VALUE);
+ // public static void trace(int, int, byte, java.lang.String)
+ Trace.trace(componentId,12,Byte.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.String, char)
+ Trace.trace(componentId,13,"hello",'X');
+ // public static void trace(int, int, char, java.lang.String)
+ Trace.trace(componentId,14,'X',"hello");
+ // public static void trace(int, int, java.lang.String, float)
+ Trace.trace(componentId,15,"hello",1.0f);
+ // public static void trace(int, int, float, java.lang.String)
+ Trace.trace(componentId,16,Double.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.String, double)
+ Trace.trace(componentId,17,"hello",Double.MAX_VALUE);
+ // public static void trace(int, int, double, java.lang.String)
+ Trace.trace(componentId,18,Double.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.Object)
+ Trace.trace(componentId,19,anyOldObject);
+ // public static void trace(int, int, java.lang.Object, java.lang.Object)
+ Trace.trace(componentId,20,anyOldObject,anotherOldObject);
+ // public static void trace(int, int, int)
+ Trace.trace(componentId,21,9);
+ // public static void trace(int, int, int, int)
+ Trace.trace(componentId,22,-1,9);
+ // public static void trace(int, int, int, int, int)
+ Trace.trace(componentId,23,999999,0,9);
+ // public static void trace(int, int, long)
+ Trace.trace(componentId,24,9L);
+ // public static void trace(int, int, long, long)
+ Trace.trace(componentId,25,0L,9L);
+ // public static void trace(int, int, long, long, long)
+ Trace.trace(componentId,26,Long.MAX_VALUE,Long.MIN_VALUE,9L);
+ // public static void trace(int, int, byte)
+ Trace.trace(componentId,27,9);
+ // public static void trace(int, int, byte, byte)
+ Trace.trace(componentId,28,-1,0);
+ // public static void trace(int, int, byte, byte, byte)
+ Trace.trace(componentId,29,Byte.MAX_VALUE,Byte.MIN_VALUE,0);
+ // public static void trace(int, int, char)
+ Trace.trace(componentId,30,'A');
+ // public static void trace(int, int, char, char)
+ Trace.trace(componentId,31,'A','B');
+ // public static void trace(int, int, char, char, char)
+ Trace.trace(componentId,32,'A','B','C');
+ // public static void trace(int, int, float)
+ Trace.trace(componentId,33,1.0f);
+ // public static void trace(int, int, float, float)
+ Trace.trace(componentId,34,Float.MAX_VALUE,Float.MIN_VALUE);
+ // public static void trace(int, int, float, float, float)
+ Trace.trace(componentId,35,Float.POSITIVE_INFINITY,Float.NEGATIVE_INFINITY,Float.NaN);
+ // public static void trace(int, int, double)
+ Trace.trace(componentId,36,999999);
+ // public static void trace(int, int, double, double)
+ Trace.trace(componentId,37,0,-1);
+ // public static void trace(int, int, double, double, double)
+ Trace.trace(componentId,38,Double.MAX_VALUE,Double.MIN_VALUE,0);
+ // public static void trace(int, int, java.lang.String, java.lang.Object, java.lang.String)
+ Trace.trace(componentId,39,"hello1",anyOldObject,"hello2");
+ // public static void trace(int, int, java.lang.Object, java.lang.String, java.lang.Object)
+ Trace.trace(componentId,40,anyOldObject,"hello",anotherOldObject);
+ // public static void trace(int, int, java.lang.String, int, java.lang.String)
+ Trace.trace(componentId,41,"hello1",9,"hello2");
+ // public static void trace(int, int, int, java.lang.String, int)
+ Trace.trace(componentId,42,9,"hello1",9);
+ // public static void trace(int, int, java.lang.String, long, java.lang.String)
+ Trace.trace(componentId,43,"hello1",9L,"hello2");
+ // public static void trace(int, int, long, java.lang.String, long)
+ Trace.trace(componentId,44,9L,"hello",9L);
+ // public static void trace(int, int, java.lang.String, byte, java.lang.String)
+ Trace.trace(componentId,45,"hello1",0,"hello2");
+ // public static void trace(int, int, byte, java.lang.String, byte)
+ Trace.trace(componentId,46,1,"hello",1);
+ // public static void trace(int, int, java.lang.String, char, java.lang.String)
+ Trace.trace(componentId,47,"hello1",'A',"hello2");
+ // public static void trace(int, int, char, java.lang.String, char)
+ Trace.trace(componentId,48,'A',"hello",'B');
+ // public static void trace(int, int, java.lang.String, float, java.lang.String)
+ Trace.trace(componentId,49,"hello1",1.0f,"hello2");
+ // public static void trace(int, int, float, java.lang.String, float)
+ Trace.trace(componentId,50,-1.0f,"hello",1.0f);
+ // public static void trace(int, int, java.lang.String, double, java.lang.String)
+ Trace.trace(componentId,51,"hello1",1,"hello2");
+ // public static void trace(int, int, double, java.lang.String, double)
+ Trace.trace(componentId,52,-1,"hello",1);
+
+ Trace.trace(componentId,53); // test passed message, validation in script
+ }
+
+ /**
+ * Re-run the trace point taking tests from TestTraceArguments to confirm
+ * that they are blocked when security is enabled. A bit long winded but it's
+ * the only way to make sure I didn't miss adding security to one of the
+ * Trace.trace() methods.
+ */
+ public void testApplicationTraceBlocked() {
+
+ System.clearProperty("com.ibm.jvm.enableLegacyTraceSecurity");
+
+ Object anyOldObject = new java.lang.Thread();
+ Object anotherOldObject = new java.lang.Thread();
+
+ int componentId = 100;
+
+ try {
+ componentId = Trace.registerApplication("TestTraceArguments",
+ TEMPLATES);
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+
+ try {
+ Trace.set("maximal=TestTraceArguments");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+
+ // Tests for all the different Trace.trace() methods
+
+ // public static void trace(int, int)
+ try {
+ Trace.trace(componentId, 0);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int)
+ try {
+ Trace.trace(componentId, 1);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String)
+ try {
+ Trace.trace(componentId, 2, "hello");
+ // java.lang.String)
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String,
+ try {
+ Trace.trace(componentId, 3, "hello1", "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String,
+ // java.lang.String, java.lang.String)
+ try {
+ Trace.trace(componentId, 4, "hello1", "hello2", "hello3");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String,
+ // java.lang.Object)
+ try {
+ Trace.trace(componentId, 5, "hello", anyOldObject);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.Object,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 6, anyOldObject, "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, int)
+ try {
+ Trace.trace(componentId, 7, "hello", 9);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, int, java.lang.String)
+ try {
+ Trace.trace(componentId, 8, 9, "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, long)
+ try {
+ Trace.trace(componentId, 9, "hello", 9L);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, long, java.lang.String)
+ try {
+ Trace.trace(componentId, 10, Long.MAX_VALUE, "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, byte)
+ try {
+ Trace.trace(componentId, 11, "hello", Byte.MAX_VALUE);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, byte, java.lang.String)
+ try {
+ Trace.trace(componentId, 12, Byte.MAX_VALUE, "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, char)
+ try {
+ Trace.trace(componentId, 13, "hello", 'X');
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, char, java.lang.String)
+ try {
+ Trace.trace(componentId, 14, 'X', "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, float)
+ try {
+ Trace.trace(componentId, 15, "hello", 1.0f);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, float, java.lang.String)
+ try {
+ Trace.trace(componentId, 16, Double.MAX_VALUE, "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, double)
+ try {
+ Trace.trace(componentId, 17, "hello", Double.MAX_VALUE);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, double, java.lang.String)
+ try {
+ Trace.trace(componentId, 18, Double.MAX_VALUE, "hello");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.Object)
+ try {
+ Trace.trace(componentId, 19, anyOldObject);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.Object,
+ // java.lang.Object)
+ try {
+ Trace.trace(componentId, 20, anyOldObject, anotherOldObject);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, int)
+ try {
+ Trace.trace(componentId, 21, 9);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, int, int)
+ try {
+ Trace.trace(componentId, 22, -1, 9);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, int, int, int)
+ try {
+ Trace.trace(componentId, 23, 999999, 0, 9);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, long)
+ try {
+ Trace.trace(componentId, 24, 9L);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, long, long)
+ try {
+ Trace.trace(componentId, 25, 0L, 9L);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, long, long, long)
+ try {
+ Trace.trace(componentId, 26, Long.MAX_VALUE, Long.MIN_VALUE, 9L);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, byte)
+ try {
+ Trace.trace(componentId, 27, 9);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, byte, byte)
+ try {
+ Trace.trace(componentId, 28, -1, 0);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, byte, byte, byte)
+ try {
+ Trace.trace(componentId, 29, Byte.MAX_VALUE, Byte.MIN_VALUE, 0);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, char)
+ try {
+ Trace.trace(componentId, 30, 'A');
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, char, char)
+ try {
+ Trace.trace(componentId, 31, 'A', 'B');
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, char, char, char)
+ try {
+ Trace.trace(componentId, 32, 'A', 'B', 'C');
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, float)
+ try {
+ Trace.trace(componentId, 33, 1.0f);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, float, float)
+ try {
+ Trace.trace(componentId, 34, Float.MAX_VALUE, Float.MIN_VALUE);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, float, float, float)
+ try {
+ Trace.trace(componentId, 35, Float.POSITIVE_INFINITY,
+ Float.NEGATIVE_INFINITY, Float.NaN);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, double)
+ try {
+ Trace.trace(componentId, 36, 999999);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, double, double)
+ try {
+ Trace.trace(componentId, 37, 0, -1);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, double, double, double)
+ try {
+ Trace.trace(componentId, 38, Double.MAX_VALUE, Double.MIN_VALUE, 0);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String,
+ // java.lang.Object, java.lang.String)
+ try {
+ Trace.trace(componentId, 39, "hello1", anyOldObject, "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.Object,
+ // java.lang.String, java.lang.Object)
+ try {
+ Trace.trace(componentId, 40, anyOldObject, "hello",
+ anotherOldObject);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, int,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 41, "hello1", 9, "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, int, java.lang.String, int)
+ try {
+ Trace.trace(componentId, 42, 9, "hello1", 9);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, long,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 43, "hello1", 9L, "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, long, java.lang.String, long)
+ try {
+ Trace.trace(componentId, 44, 9L, "hello", 9L);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, byte,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 45, "hello1", 0, "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, byte, java.lang.String, byte)
+ try {
+ Trace.trace(componentId, 46, 1, "hello", 1);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, char,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 47, "hello1", 'A', "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, char, java.lang.String, char)
+ try {
+ Trace.trace(componentId, 48, 'A', "hello", 'B');
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, float,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 49, "hello1", 1.0f, "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, float, java.lang.String,
+ // float)
+ try {
+ Trace.trace(componentId, 50, -1.0f, "hello", 1.0f);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, java.lang.String, double,
+ // java.lang.String)
+ try {
+ Trace.trace(componentId, 51, "hello1", 1, "hello2");
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ // public static void trace(int, int, double, java.lang.String,
+ // double)
+ try {
+ Trace.trace(componentId, 52, -1, "hello", 1);
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ try {
+ Trace.trace(componentId, 53); // test passed message
+ fail("Expected SecurityException to be thrown");
+ } catch (SecurityException e) {
+ /* Pass */
+ }
+ }
+
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/GenerateJavaCoreAndSnap.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/GenerateJavaCoreAndSnap.java
new file mode 100644
index 00000000000..be8287af91e
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/GenerateJavaCoreAndSnap.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+/*
+* Generate a javacore and snap dump via the dump and trace APIs for
+* use with TestJavaCoreAndSnap
+*/
+
+public class GenerateJavaCoreAndSnap {
+
+ public static void main(String[] args) {
+
+ System.out.println("GenerateJavaCoreAndSnap: started");
+
+ // Take a javacore
+ com.ibm.jvm.Dump.JavaDump();
+
+ // Take a snap dump
+ com.ibm.jvm.Trace.snap();
+
+ System.out.println("GenerateJavaCoreAndSnap: finished");
+
+ }
+
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestGetMicros.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestGetMicros.java
new file mode 100644
index 00000000000..3526275525a
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestGetMicros.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestGetMicros {
+
+ public static void main(String[] args) {
+
+ System.out.println("TestGetMicros: started");
+
+ long startMicroTime = Trace.getMicros();
+ long stopMicroTime = 0;
+
+ /* Wait 10 seconds. */
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e ) {
+ // Do nothing.
+ }
+ stopMicroTime = Trace.getMicros();
+
+ long microDuration = stopMicroTime - startMicroTime;
+
+ // Is the duration > 0 and less than a minute?
+ if( microDuration > 0 && microDuration < 60*(1000000) ) {
+ System.out.println("TestGetMicros: TEST PASSED");
+ System.exit(0);
+ } else {
+ System.out.println("TestGetMicros: TEST FAILED");
+ System.out.printf("Start time was %d, end time was %d, duration was %d\n", startMicroTime, stopMicroTime, microDuration);
+ System.exit(1);
+ }
+ }
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestJavaCoreAndSnap.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestJavaCoreAndSnap.java
new file mode 100644
index 00000000000..0330a3ca43f
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestJavaCoreAndSnap.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+/*
+ * Compare the current thread trace from a javacore and a snap trace file
+ * (formatted to only contain that thread) to make sure the data is the same.
+ *
+ * The javacore and snap dump should have been taken as close together as possible.
+ */
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+public class TestJavaCoreAndSnap {
+
+ private static final String XEHSTTYPE = "3XEHSTTYPE ";
+
+ public static void main(String[] args) {
+
+ System.out.println("TestJavaCoreAndSnap: started");
+
+ if( args.length != 2 ) {
+ System.err.println("Expected two arguments, javacore and formatted snap trace.");
+ exit(1);
+ }
+
+ String javacoreFileName = args[0];
+ String traceFileName = args[1];
+
+ System.out.printf("Comparing current thread trace in %s and %s\n", javacoreFileName, traceFileName);
+
+ String[] jcTrace = extractJCTrace(javacoreFileName);
+
+ String lastTPid = getTracePointId(jcTrace[0]);
+
+ //System.err.println("Last tpid is: " + lastTPid);
+
+ String[] snapTrace = extractFormattedTrace(traceFileName);
+
+ int jcTraceIndex = 0;
+ int snapTraceIndex = 0;
+ boolean found = false;
+
+ /* The test expects the snap trace to have been taken after the javacore.
+ * To enable us to match the trace points up skip the first few tracepoints in the
+ * snap file until we get to the one that mentions the javacore (and which should be
+ * the last trace point in the javacore).
+ */
+ for( ; snapTraceIndex < snapTrace.length; snapTraceIndex++) {
+ //System.err.println("Checking id: " + getTracePointId(snapTrace[snapTraceIndex]) + " from " + snapTrace[snapTraceIndex]);
+ if( "j9dmp.9".equals(getTracePointId(snapTrace[snapTraceIndex])) &&
+ snapTrace[snapTraceIndex].contains(javacoreFileName) ) {
+ found = true;
+ //System.err.println("snapTraceIndex is: " + snapTraceIndex);
+ break;
+ }
+ }
+
+ if( found == false ) {
+ System.err.println("Couldn't match start of trace in java core to start of trace in snap.");
+ exit(2);
+ }
+
+ for( ; snapTraceIndex < snapTrace.length && jcTraceIndex < jcTrace.length; snapTraceIndex++, jcTraceIndex++) {
+ String snapTraceLine = snapTrace[snapTraceIndex];
+ String jcTraceLine = jcTrace[jcTraceIndex];
+ String snapTraceID = getTracePointId(snapTraceLine);
+ String jcTraceID = getTracePointId(jcTraceLine);
+ if( !snapTraceID.equals(jcTraceID) ) {
+ System.err.println("Trace point lines did not match:" + jcTraceID + " vs " + snapTraceID );
+ System.err.println("Javacore: " + jcTraceLine);
+ System.err.println("Snap trace: " + snapTraceLine);
+
+ exit(3);
+ } else {
+// System.err.println("Trace point lines matched:" + jcTraceID + " vs " + snapTraceID );
+ }
+ // Checking the content would be good *but* things like number formatting (with or without leading
+ // 0's) make it impractical even if we ignore the case.
+/* String snapTraceDetail = getTracePointDetail(snapTraceLine);
+ String jcTraceDetail = getTracePointDetail(jcTraceLine);
+ if( !snapTraceDetail.equalsIgnoreCase(jcTraceDetail) ) {
+ System.err.println("Trace point lines did not match:" + jcTraceID + " vs " + snapTraceID );
+ System.err.println("Javacore: '" + jcTraceDetail + "'");
+ System.err.println("Snap trace: '" + snapTraceDetail + "'");
+
+ exit(3);
+ } else {
+ System.err.println("Trace point lines matched:" + jcTraceDetail + " vs " + snapTraceDetail );
+ }*/
+ }
+
+ exit(0);
+
+ }
+
+ private static void exit(int code) {
+ if( code == 0 ) {
+ System.out.println("TestJavaCoreAndSnap: passed");
+ } else {
+ System.out.println("TestJavaCoreAndSnap: failed");
+ }
+ System.out.println("TestJavaCoreAndSnap: finished");
+ System.exit(code);
+ }
+
+ private static String[] extractJCTrace(String javacoreFileName) {
+
+ BufferedReader in = null;
+ List traceLines = new LinkedList();
+
+ try {
+ try {
+ in = new BufferedReader(new FileReader(javacoreFileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + javacoreFileName + " not found.");
+ return null;
+ }
+
+ String str;
+ try {
+ while( (str = in.readLine()) != null ) {
+ if( str.startsWith(XEHSTTYPE) ) {
+ traceLines.add(str.substring(XEHSTTYPE.length()));
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Failed to read from file: " + javacoreFileName);
+ return null;
+ }
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // Not much we can do about this.
+ }
+ }
+
+ return traceLines.toArray(new String[0]);
+
+ }
+
+ private static String[] extractFormattedTrace(String traceFileName) {
+
+ BufferedReader in = null;
+ List traceLines = new LinkedList();
+
+ try {
+ try {
+ in = new BufferedReader(new FileReader(traceFileName));
+ } catch (FileNotFoundException e) {
+ System.err.println("File: " + traceFileName + " not found.");
+ return null;
+ }
+
+ String str;
+ try {
+ while( (str = in.readLine()) != null ) {
+ if( str.startsWith("Time") ) {
+ // The next line is the start of the actual trace,
+ // we're past the header information.
+ break;
+ }
+ }
+ while( (str = in.readLine()) != null ) {
+ // Add these to the start of the list to reverse them into the same order as
+ // the ones from javacore.
+ traceLines.add(0, str);
+ }
+ } catch (IOException e) {
+ System.err.println("Failed to read from file: " + traceFileName);
+ return null;
+ }
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // Not much we can do about this.
+ }
+ }
+
+ return traceLines.toArray(new String[0]);
+
+ }
+
+ // This works for both javacore trace and snap trace because javacore has the timezone in
+ // position 1 and formatted snap trace has the thread id in the same column.
+ private static String getTracePointId(String traceLine) {
+ return traceLine.split("\\s+")[2];
+ }
+
+ private static String getTracePointDetail(String traceLine) {
+ return traceLine.split("\\s+",5)[4].trim();
+ }
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestMultipleApplications.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestMultipleApplications.java
new file mode 100644
index 00000000000..e090e591593
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestMultipleApplications.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestMultipleApplications {
+
+ public static void main(String[] args) {
+
+ String[] templates = new String[4];
+
+ System.out.println("TestMultipleApplications: started");
+ templates[0] = Trace.EVENT;
+ templates[1] = Trace.EVENT + "Tracepoint #01 %s";
+ templates[2] = Trace.EVENT + "Tracepoint #02 %s";
+ templates[3] = Trace.EVENT + "Tracepoint #03 %s";
+
+ int componentId1 = Trace.registerApplication("App1",templates);
+ int componentId2 = Trace.registerApplication("App2",templates);
+
+ Trace.set("print={App1,App2}");
+
+ // Trace from both components.
+ Trace.trace(componentId1, 1, "from application 1");
+ Trace.trace(componentId2, 1, "from application 2");
+ Trace.trace(componentId1, 2, "from application 1");
+ Trace.trace(componentId2, 2, "from application 2");
+ Trace.trace(componentId1, 3, "from application 1");
+ Trace.trace(componentId2, 3, "from application 2");
+
+ System.out.println("TestMultipleApplications: finished");
+
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSnap.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSnap.java
new file mode 100644
index 00000000000..dae5dc0825c
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSnap.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestSnap {
+
+ public static void main(String[] args) {
+
+ System.out.println("TestSnap: started");
+
+ // Test the Trace.snap() method
+ Trace.snap();
+
+ System.out.println("TestSnap: finished");
+
+ }
+
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSuspendResume.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSuspendResume.java
new file mode 100644
index 00000000000..eb55b245125
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSuspendResume.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestSuspendResume {
+
+ public static void main(String[] args) {
+
+ String[] templates = new String[4];
+
+ System.out.println("TestSuspendResume: started");
+ templates[0] = Trace.EVENT;
+ templates[1] = Trace.EVENT + "Tracepoint #01";
+ templates[2] = Trace.EVENT + "Tracepoint #02 Error: TEST FAILED";
+ templates[3] = Trace.EVENT + "Tracepoint #03";
+
+
+ final int componentId = Trace.registerApplication("TestSuspendResume",templates);
+ Trace.set("print=TestSuspendResume");
+ Trace.trace(componentId,1);
+
+ // Test the Trace.suspend() method
+ Trace.suspend();
+ Trace.trace(componentId,2); // trace suspended, so this tracepoint should not appear
+
+ /* Check that trace *is not* produced on another thread. */
+ Thread t = new Thread() {
+
+ public void run() {
+ Trace.trace(componentId, 1);
+ Trace.trace(componentId, 2);
+ Trace.trace(componentId, 3);
+ }
+
+ };
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Test the Trace.resume() method
+ Trace.resume();
+ Trace.trace(componentId,3);
+
+ System.out.println("TestSuspendResume: finished");
+
+ }
+
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSuspendResumeThis.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSuspendResumeThis.java
new file mode 100644
index 00000000000..fff09d4e506
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestSuspendResumeThis.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestSuspendResumeThis {
+
+
+ public static void main(String[] args) {
+
+ String[] templates = new String[4];
+
+ System.out.println("TestSuspendResumeThis: started");
+ templates[0] = Trace.EVENT;
+ templates[1] = Trace.EVENT + "Tracepoint #01 Thread: %s";
+ templates[2] = Trace.EVENT + "Tracepoint #02 Thread: %s";
+ templates[3] = Trace.EVENT + "Tracepoint #03 Thread: %s";
+
+
+ final int componentId = Trace.registerApplication("TestSuspendResumeThis",templates);
+ Trace.set("print=TestSuspendResumeThis");
+ Trace.trace(componentId, 1, Thread.currentThread().getName());
+
+ // Test the Trace.suspendThis() method
+ Trace.suspendThis();
+ Trace.trace(componentId, 2, Thread.currentThread().getName()); // trace suspended, so this tracepoint should not appear
+
+ /* Check that trace *is* still produced on another thread. */
+ Thread t = new Thread() {
+
+ public void run() {
+ Trace.trace(componentId, 1, Thread.currentThread().getName());
+ Trace.trace(componentId, 2, Thread.currentThread().getName());
+ Trace.trace(componentId, 3, Thread.currentThread().getName());
+ }
+
+ };
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Test the Trace.resumeThis() method
+ Trace.resumeThis();
+ Trace.trace(componentId, 3, Thread.currentThread().getName());
+
+ System.out.println("TestSuspendResumeThis: finished");
+
+ }
+
+}
+
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestTraceArguments.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestTraceArguments.java
new file mode 100644
index 00000000000..dee4541a6da
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestTraceArguments.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestTraceArguments {
+
+ public static void main(String[] args) {
+
+ String[] templates = new String[54];
+ Object anyOldObject = new java.lang.Thread();
+ Object anotherOldObject = new java.lang.Thread();
+
+ System.out.println("TestTraceArguments: started");
+
+ templates[0] = Trace.EVENT;
+ templates[1] = Trace.EVENT + "Tracepoint #1 ";
+ templates[2] = Trace.EVENT + "Tracepoint #2 insert1=%s";
+ templates[3] = Trace.EVENT + "Tracepoint #3 insert1=%s insert2=%s";
+ templates[4] = Trace.EVENT + "Tracepoint #4 insert1=%s insert2=%s insert3=%s";
+ templates[5] = Trace.EVENT + "Tracepoint #5 insert1=%s insert2=%p";
+ templates[6] = Trace.EVENT + "Tracepoint #6 insert1=%p insert2=%s";
+ templates[7] = Trace.EVENT + "Tracepoint #7 insert1=%s insert2=%d";
+ templates[8] = Trace.EVENT + "Tracepoint #8 insert1=%d insert2=%s";
+ templates[9] = Trace.EVENT + "Tracepoint #9 insert1=%s insert2=%lld";
+ templates[10] = Trace.EVENT + "Tracepoint #10 insert1=%lld insert2=%s"; // mkomine@77003
+ templates[11] = Trace.EVENT + "Tracepoint #11 insert1=%s insert2=%d";
+ templates[12] = Trace.EVENT + "Tracepoint #12 insert1=%d insert2=%s";
+ templates[13] = Trace.EVENT + "Tracepoint #13 insert1=%s insert2=%c";
+ templates[14] = Trace.EVENT + "Tracepoint #14 insert1=%c insert2=%s";
+ templates[15] = Trace.EVENT + "Tracepoint #15 insert1=%s insert2=%f";
+ templates[16] = Trace.EVENT + "Tracepoint #16 insert1=%e insert2=%s";
+ templates[17] = Trace.EVENT + "Tracepoint #17 insert1=%s insert2=%e";
+ templates[18] = Trace.EVENT + "Tracepoint #18 insert1=%e insert2=%s";
+ templates[19] = Trace.EVENT + "Tracepoint #19 insert1=%p";
+ templates[20] = Trace.EVENT + "Tracepoint #20 insert1=%p insert2=%p";
+ templates[21] = Trace.EVENT + "Tracepoint #21 insert1=%d";
+ templates[22] = Trace.EVENT + "Tracepoint #22 insert1=%d insert2=%d";
+ templates[23] = Trace.EVENT + "Tracepoint #23 insert1=%d insert2=%d insert3=%d";
+ templates[24] = Trace.EVENT + "Tracepoint #24 insert1=%lld";
+ templates[25] = Trace.EVENT + "Tracepoint #25 insert1=%lld insert2=%lld";
+ templates[26] = Trace.EVENT + "Tracepoint #26 insert1=%lld insert2=%lld insert3=%lld";
+ templates[27] = Trace.EVENT + "Tracepoint #27 insert1=%d";
+ templates[28] = Trace.EVENT + "Tracepoint #28 insert1=%d insert2=%d";
+ templates[29] = Trace.EVENT + "Tracepoint #29 insert1=%d insert2=%d insert3=%d";
+ templates[30] = Trace.EVENT + "Tracepoint #30 insert1=%c";
+ templates[31] = Trace.EVENT + "Tracepoint #31 insert1=%c insert2=%c";
+ templates[32] = Trace.EVENT + "Tracepoint #32 insert1=%c insert2=%c insert3=%c";
+ templates[33] = Trace.EVENT + "Tracepoint #33 insert1=%f";
+ templates[34] = Trace.EVENT + "Tracepoint #34 insert1=%e insert2=%e";
+ templates[35] = Trace.EVENT + "Tracepoint #35 insert1=%f insert2=%f insert3=%f";
+ templates[36] = Trace.EVENT + "Tracepoint #36 insert1=%d";
+ templates[37] = Trace.EVENT + "Tracepoint #37 insert1=%d insert2=%d";
+ templates[38] = Trace.EVENT + "Tracepoint #38 insert1=%f insert2=%f insert3=%f";
+ templates[39] = Trace.EVENT + "Tracepoint #39 insert1=%s insert2=%p insert3=%s";
+ templates[40] = Trace.EVENT + "Tracepoint #40 insert1=%p insert2=%s insert3=%p";
+ templates[41] = Trace.EVENT + "Tracepoint #41 insert1=%s insert2=%d insert3=%s";
+ templates[42] = Trace.EVENT + "Tracepoint #42 insert1=%d insert2=%s insert3=%d";
+ templates[43] = Trace.EVENT + "Tracepoint #43 insert1=%s insert2=%lld insert3=%s";
+ templates[44] = Trace.EVENT + "Tracepoint #44 insert1=%lld insert2=%s insert3=%lld";
+ templates[45] = Trace.EVENT + "Tracepoint #45 insert1=%s insert2=%d insert3=%s";
+ templates[46] = Trace.EVENT + "Tracepoint #46 insert1=%d insert2=%s insert3=%d";
+ templates[47] = Trace.EVENT + "Tracepoint #47 insert1=%s insert2=%c insert3=%s";
+ templates[48] = Trace.EVENT + "Tracepoint #48 insert1=%c insert2=%s insert3=%c";
+ templates[49] = Trace.EVENT + "Tracepoint #49 insert1=%s insert2=%f insert3=%s";
+ templates[50] = Trace.EVENT + "Tracepoint #50 insert1=%f insert2=%s insert3=%f";
+ templates[51] = Trace.EVENT + "Tracepoint #51 insert1=%s insert2=%d insert3=%s";
+ templates[52] = Trace.EVENT + "Tracepoint #52 insert1=%d insert2=%s insert3=%d";
+ templates[53] = Trace.EVENT + "Tracepoint #53 TEST PASSED";
+
+ int componentId = Trace.registerApplication("TestTraceArguments",templates);
+
+ Trace.set("print=TestTraceArguments");
+
+ // Tests for all the different Trace.trace() methods
+
+ // public static void trace(int, int)
+ Trace.trace(componentId,0);
+ // public static void trace(int, int)
+ Trace.trace(componentId,1);
+ // public static void trace(int, int, java.lang.String)
+ Trace.trace(componentId,2,"hello");
+ // public static void trace(int, int, java.lang.String, java.lang.String)
+ Trace.trace(componentId,3,"hello1","hello2");
+ // public static void trace(int, int, java.lang.String, java.lang.String, java.lang.String)
+ Trace.trace(componentId,4,"hello1","hello2","hello3");
+ // public static void trace(int, int, java.lang.String, java.lang.Object)
+ Trace.trace(componentId,5,"hello",anyOldObject);
+ // public static void trace(int, int, java.lang.Object, java.lang.String)
+ Trace.trace(componentId,6,anyOldObject,"hello");
+ // public static void trace(int, int, java.lang.String, int)
+ Trace.trace(componentId,7,"hello",9);
+ // public static void trace(int, int, int, java.lang.String)
+ Trace.trace(componentId,8,9,"hello");
+ // public static void trace(int, int, java.lang.String, long)
+ Trace.trace(componentId,9,"hello",9L);
+ // public static void trace(int, int, long, java.lang.String)
+ Trace.trace(componentId,10,Long.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.String, byte)
+ Trace.trace(componentId,11,"hello",Byte.MAX_VALUE);
+ // public static void trace(int, int, byte, java.lang.String)
+ Trace.trace(componentId,12,Byte.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.String, char)
+ Trace.trace(componentId,13,"hello",'X');
+ // public static void trace(int, int, char, java.lang.String)
+ Trace.trace(componentId,14,'X',"hello");
+ // public static void trace(int, int, java.lang.String, float)
+ Trace.trace(componentId,15,"hello",1.0f);
+ // public static void trace(int, int, float, java.lang.String)
+ Trace.trace(componentId,16,Double.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.String, double)
+ Trace.trace(componentId,17,"hello",Double.MAX_VALUE);
+ // public static void trace(int, int, double, java.lang.String)
+ Trace.trace(componentId,18,Double.MAX_VALUE,"hello");
+ // public static void trace(int, int, java.lang.Object)
+ Trace.trace(componentId,19,anyOldObject);
+ // public static void trace(int, int, java.lang.Object, java.lang.Object)
+ Trace.trace(componentId,20,anyOldObject,anotherOldObject);
+ // public static void trace(int, int, int)
+ Trace.trace(componentId,21,9);
+ // public static void trace(int, int, int, int)
+ Trace.trace(componentId,22,-1,9);
+ // public static void trace(int, int, int, int, int)
+ Trace.trace(componentId,23,999999,0,9);
+ // public static void trace(int, int, long)
+ Trace.trace(componentId,24,9L);
+ // public static void trace(int, int, long, long)
+ Trace.trace(componentId,25,0L,9L);
+ // public static void trace(int, int, long, long, long)
+ Trace.trace(componentId,26,Long.MAX_VALUE,Long.MIN_VALUE,9L);
+ // public static void trace(int, int, byte)
+ Trace.trace(componentId,27,9);
+ // public static void trace(int, int, byte, byte)
+ Trace.trace(componentId,28,-1,0);
+ // public static void trace(int, int, byte, byte, byte)
+ Trace.trace(componentId,29,Byte.MAX_VALUE,Byte.MIN_VALUE,0);
+ // public static void trace(int, int, char)
+ Trace.trace(componentId,30,'A');
+ // public static void trace(int, int, char, char)
+ Trace.trace(componentId,31,'A','B');
+ // public static void trace(int, int, char, char, char)
+ Trace.trace(componentId,32,'A','B','C');
+ // public static void trace(int, int, float)
+ Trace.trace(componentId,33,1.0f);
+ // public static void trace(int, int, float, float)
+ Trace.trace(componentId,34,Float.MAX_VALUE,Float.MIN_VALUE);
+ // public static void trace(int, int, float, float, float)
+ Trace.trace(componentId,35,Float.POSITIVE_INFINITY,Float.NEGATIVE_INFINITY,Float.NaN);
+ // public static void trace(int, int, double)
+ Trace.trace(componentId,36,999999);
+ // public static void trace(int, int, double, double)
+ Trace.trace(componentId,37,0,-1);
+ // public static void trace(int, int, double, double, double)
+ Trace.trace(componentId,38,Double.MAX_VALUE,Double.MIN_VALUE,0);
+ // public static void trace(int, int, java.lang.String, java.lang.Object, java.lang.String)
+ Trace.trace(componentId,39,"hello1",anyOldObject,"hello2");
+ // public static void trace(int, int, java.lang.Object, java.lang.String, java.lang.Object)
+ Trace.trace(componentId,40,anyOldObject,"hello",anotherOldObject);
+ // public static void trace(int, int, java.lang.String, int, java.lang.String)
+ Trace.trace(componentId,41,"hello1",9,"hello2");
+ // public static void trace(int, int, int, java.lang.String, int)
+ Trace.trace(componentId,42,9,"hello1",9);
+ // public static void trace(int, int, java.lang.String, long, java.lang.String)
+ Trace.trace(componentId,43,"hello1",9L,"hello2");
+ // public static void trace(int, int, long, java.lang.String, long)
+ Trace.trace(componentId,44,9L,"hello",9L);
+ // public static void trace(int, int, java.lang.String, byte, java.lang.String)
+ Trace.trace(componentId,45,"hello1",0,"hello2");
+ // public static void trace(int, int, byte, java.lang.String, byte)
+ Trace.trace(componentId,46,1,"hello",1);
+ // public static void trace(int, int, java.lang.String, char, java.lang.String)
+ Trace.trace(componentId,47,"hello1",'A',"hello2");
+ // public static void trace(int, int, char, java.lang.String, char)
+ Trace.trace(componentId,48,'A',"hello",'B');
+ // public static void trace(int, int, java.lang.String, float, java.lang.String)
+ Trace.trace(componentId,49,"hello1",1.0f,"hello2");
+ // public static void trace(int, int, float, java.lang.String, float)
+ Trace.trace(componentId,50,-1.0f,"hello",1.0f);
+ // public static void trace(int, int, java.lang.String, double, java.lang.String)
+ Trace.trace(componentId,51,"hello1",1,"hello2");
+ // public static void trace(int, int, double, java.lang.String, double)
+ Trace.trace(componentId,52,-1,"hello",1);
+
+ Trace.trace(componentId,53); // test passed message, validation in script
+ System.out.println("TestTraceArguments: finished");
+
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestTraceTypes.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestTraceTypes.java
new file mode 100644
index 00000000000..ea9b45aaa53
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/apptrace/TestTraceTypes.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.apptrace;
+
+import com.ibm.jvm.Trace;
+
+public class TestTraceTypes {
+
+ public static void main(String[] args) {
+
+ String[] templates = new String[5];
+
+ System.out.println("TestMultipleApplications: started");
+ templates[0] = Trace.EVENT;
+ templates[1] = Trace.EVENT + "Tracepoint #01 - Event Type";
+ templates[2] = Trace.ENTRY+ "Tracepoint #02 - Entry Type";
+ templates[3] = Trace.EXIT + "Tracepoint #03 - Exit Type";
+ templates[4] = Trace.EXCEPTION_EXIT + "Tracepoint #04 - Exception Exit Type";
+
+ int componentId = Trace.registerApplication("TestTraceTypes",templates);
+
+ Trace.set("print=TestTraceTypes");
+
+ // Trace from both components.
+ Trace.trace(componentId, 1);
+ Trace.trace(componentId, 2);
+ Trace.trace(componentId, 3);
+ Trace.trace(componentId, 4);
+
+ System.out.println("TestTraceTypes: finished");
+
+ }
+
+}
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/jstacktrace/HelloWorld.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/jstacktrace/HelloWorld.java
new file mode 100644
index 00000000000..187565d0540
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/jstacktrace/HelloWorld.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.jstacktrace;
+
+public class HelloWorld
+{
+
+ public static void main(String args[]) {
+ System.err.println("Hello, world");
+ }
+
+}
\ No newline at end of file
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/jstacktrace/TriggerDumpTracePoint.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/jstacktrace/TriggerDumpTracePoint.java
new file mode 100644
index 00000000000..32b422ade1d
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/jstacktrace/TriggerDumpTracePoint.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.jstacktrace;
+
+/*
+ * Licensed Materials - Property of IBM
+ * (C) Copyright IBM Corp. 2009. All Rights Reserved.
+ * US Government Users Restricted Rights - Use, duplication or
+ * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+ */
+
+/**
+ * This class is used to trigger a tracepoint in the dump system by calling
+ * the com.ibm.jvm.Dump API.
+ *
+ * Andrew Hall
+ * andhall@uk.ibm.com
+ */
+public class TriggerDumpTracePoint
+{
+
+ public static void main(String args[]) {
+ com.ibm.jvm.Dump.JavaDump();
+ }
+
+}
\ No newline at end of file
diff --git a/test/functional/RasapiTest/src/com/ibm/trace/tests/trace_subscriber/TraceQueue.java b/test/functional/RasapiTest/src/com/ibm/trace/tests/trace_subscriber/TraceQueue.java
new file mode 100644
index 00000000000..e5b5e7831fe
--- /dev/null
+++ b/test/functional/RasapiTest/src/com/ibm/trace/tests/trace_subscriber/TraceQueue.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2021 IBM Corp. and others
+ *
+ * This program and the accompanying materials are made available under
+ * the terms of the Eclipse Public License 2.0 which accompanies this
+ * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
+ * or the Apache License, Version 2.0 which accompanies this distribution and
+ * is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * This Source Code may also be made available under the following
+ * Secondary Licenses when the conditions for such availability set
+ * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
+ * General Public License, version 2 with the GNU Classpath
+ * Exception [1] and GNU General Public License, version 2 with the
+ * OpenJDK Assembly Exception [2].
+ *
+ * [1] https://www.gnu.org/software/classpath/license.html
+ * [2] http://openjdk.java.net/legal/assembly-exception.html
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
+ *******************************************************************************/
+package com.ibm.trace.tests.trace_subscriber;
+
+public class TraceQueue {
+ public static void main(String[] args) {
+ int result = 0;
+ int publishers = 0;
+ int subscribers = 0;
+
+ /* invoked with com.ibm.ras.tests.TraceQueue publishers subscribers */
+ if (args.length == 2) {
+ try {
+ publishers = Integer.parseInt(args[0]);
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid value specified for publishers, requires an integer greater than 0");
+ result = -1;
+ }
+
+ try {
+ subscribers = Integer.parseInt(args[1]);
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid value specified for subscribers, requires an integer greater than 0");
+ result = -1;
+ }
+ }
+
+ /* print usage if there's been a problem */
+ if (args.length != 2 || result != 0) {
+ System.err.println("Usage: com.ibm.ras.tests.TraceQueue publishers subscribers");
+ System.exit(-1);
+ }
+
+ /* try running the test */
+ if (!runQueueTests(subscribers, publishers)) {
+ System.err.println("FAILED");
+ result = -2;
+ } else {
+ System.out.println("PASSED");
+ result = 0;
+ }
+
+ System.exit(result);
+ }
+
+ public static native boolean runQueueTests(int subscribers, int publishers);
+}
\ No newline at end of file
diff --git a/test/functional/RasapiTest/test.xml b/test/functional/RasapiTest/test.xml
new file mode 100644
index 00000000000..31fd330a4d3
--- /dev/null
+++ b/test/functional/RasapiTest/test.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+ Ant script to run the tests for the com.ibm.jvm.Dump API.
+ First it runs the suite of tests defined in DumpAPISuite
+ Then it runs the Security tests with security on and the permission not granted.
+ This should show the correct methods are blocked.
+ Then it adds com.ibm.jvm.DumpPermssion to the security file and reruns the Basic and
+ QuerySetReset tests to confirm they work when security is on.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file