undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,109 @@
#
# Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# This is a temporary standalone makefile
#
BUILD_DIR := $(shell pwd)/build
CLASSES_DIR := ${BUILD_DIR}/classes
IMAGE_DIR := ${BUILD_DIR}/image
RUN_DIR := $(shell pwd)/run
CLASSPATH := ${JTREG_HOME}/lib/jtreg.jar:${JAVA_HOME}/lib/tools.jar
SRC_DIR := src/share/classes/
SOURCES := ${SRC_DIR}/jdk/test/failurehandler/*.java \
${SRC_DIR}/jdk/test/failurehandler/action/*.java \
${SRC_DIR}/jdk/test/failurehandler/jtreg/*.java \
${SRC_DIR}/jdk/test/failurehandler/value/*.java
CONF_DIR = src/share/conf
JAVA_RELEASE = 15
TARGET_JAR = ${IMAGE_DIR}/lib/jtregFailureHandler.jar
OS_NAME := $(shell uname -o 2>&1)
ifeq ("${OS_NAME}", "Cygwin")
BUILD_DIR := $(shell cygpath -m "${BUILD_DIR}")
CLASSES_DIR := $(shell cygpath -m "${CLASSES_DIR}")
IMAGE_DIR := $(shell cygpath -m "${IMAGE_DIR}")
RUN_DIR := $(shell cygpath -m "${RUN_DIR}")
SRC_DIR := $(shell cygpath -m "${SRC_DIR}")
JAVA_HOME := $(shell cygpath -m "${JAVA_HOME}")
JTREG_HOME := $(shell cygpath -m "${JTREG_HOME}")
CLASSPATH := $(shell cygpath -pm "${CLASSPATH}")
endif
all: clean test
check_defined = $(foreach 1,$1,$(__check_defined))
__check_defined = $(if $(value $1),, $(error $1 is not set))
classes: require_env
mkdir -p ${IMAGE_DIR}/bin ${IMAGE_DIR}/lib ${CLASSES_DIR}
"${JAVA_HOME}"/bin/javac -target ${JAVA_RELEASE} -source ${JAVA_RELEASE} \
-sourcepath "$(shell pwd)" \
-cp "${CLASSPATH}" \
-d ${CLASSES_DIR} \
${SOURCES}
"${JAVA_HOME}"/bin/jar cf "${TARGET_JAR}" -C "${CLASSES_DIR}" .
"${JAVA_HOME}"/bin/jar uf "${TARGET_JAR}" -C "${CONF_DIR}" .
#
# Use JTREG_TEST_OPTS for test VM options
# Use JTREG_TESTS for jtreg tests parameter
#
test: require_env build
rm -rf "${RUN_DIR}"
mkdir -p "${RUN_DIR}"
"${JTREG_HOME}"/bin/jtreg \
-jdk:"${JAVA_HOME}" \
${JTREG_TEST_OPTS} \
-timeout:0.1 -va -retain:all \
-noreport \
-agentvm \
-thd:"${TARGET_JAR}" \
-th:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler \
-thtimeout:0 \
-od:"${TARGET_JAR}" \
-o:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \
-w:"${RUN_DIR}/JTwork" \
-r:"${RUN_DIR}/JTreport" \
$(if ${JTREG_TESTS}, ${JTREG_TESTS}, test) \
&& false || true
debug: JTREG_TEST_OPTS += "-J-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005'"
debug: test
require_env:
$(call check_defined, JAVA_HOME)
$(call check_defined, JTREG_HOME)
clean:
rm -rf "${BUILD_DIR}" "${RUN_DIR}"
build: classes
.PHONY: all build classes test require_env clean
.DEFAULT: all

116
test/failure_handler/README Normal file
View file

@ -0,0 +1,116 @@
Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
DESCRIPTION
The purpose of this library is gathering diagnostic information on test
failures and timeouts. The library runs platform specific tools, which are
configured in the way described below. The collected data will be available
in HTML format next to JTR files.
The library uses JTHarness Observer and jtreg TimeoutHandler extensions points.
DEPENDENCES
The library requires jtreg 4b13+ and JDK 15+.
BUILDING
The library is built using the top level build-test-failure-handler target and
is automatically included in the test image and picked up by hotspot and jdk
test makefiles.
CONFIGURATION
Properties files are used to configure the library. They define which actions
to be performed in case of individual test failure or timeout. Each platform
family uses its own property file (named '<platform>.properties'). For platform
independent actions, 'common.properties' is used.
Actions to be performed on each failure are listed in 'environment' property.
Extra actions for timeouts are listed in 'onTimeout'.
Each action is defined via the following parameters:
- 'javaOnly' -- run the action only for java applications, false by default
- 'app' -- an application to run, mandatory parameter
- 'args' -- application command line arguments, none by default
- 'params' -- a structure which defines how an application should be run,
described below
Actions listed in 'onTimeout' are "patterned" actions. Besides the parameters
listed above, they also have 'pattern' parameter -- a string which will be
replaced by PID in 'args' parameter before action execution.
'params' structure has the following parameters:
- repeat -- how many times an action will be run, 1 by default
- pause -- delay in ms between iterations, 500 by default
- timeout -- time limitation for iteration in ms, 20 000 by default
- stopOnError -- if true, an action will be interrupted after the first error,
false by default
From '<platform>.properties', the library reads the following parameters
- 'config.execSuffix' -- a suffix for all binary application file names
- 'config.getChildren' -- a "patterned" action used to get the list of all
children
For simplicity we use parameter values inheritance. This means that we are
looking for the most specified parameter value. If we do not find it, we are
trying to find less specific value by reducing prefix.
For example, if properties contains 'p1=A', 'a.p1=B', 'a.b.p1=C', then
parameter 'p1' will be:
- 'C' for 'a.b.c'
- 'B' for 'a.c'
- 'A' for 'b.c'
RUNNING
To enable the library in jtreg, the following options should be set:
- '-timeoutHandlerDir' points to the built jar ('jtregFailureHandler.jar')
- '-observerDir' points to the built jar
- '-timeoutHandler' equals to jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler
- '-observer' equals to jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver
In case of environment issues during an action execution, such as missing
application, hung application, lack of disk space, etc, the corresponding
warning appears and the library proceeds to next action.
EXAMPLES
$ ${JTREG_HOME}/bin/jtreg -jdk:${JAVA_HOME} \
-timeoutHandlerDir:./image/lib/jtregFailureHandler.jar \
-observerDir:./image/lib/jtregFailureHandler.jar \
-timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler\
-observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \
${WS}/hotspot/test/
TESTING
There are a few make targets for testing the failure_handler itself.
- Everything in `test/failure_handler/Makefile`
- The `test-failure-handler` target in `make/RunTests.gmk`
- The `test` target in `make/test/BuildFailureHandler.gmk`
All of these targets are written for manual testing only. They rely on
manual inspection of generated artifacts and cannot be run as part of a CI.
They are tests which timeout, crash, fail in various ways and you can check
the failure_handler output yourself. They might also leave processes running
on your machine so be extra careful about cleaning up.

View file

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

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;
public class ElapsedTimePrinter implements AutoCloseable {
private final String name;
private final PrintWriter out;
private final Stopwatch stopwatch;
public ElapsedTimePrinter(Stopwatch stopwatch, String name,
PrintWriter out) {
this.stopwatch = stopwatch;
this.name = name;
this.out = out;
stopwatch.start();
}
@Override
public void close() {
stopwatch.stop();
out.printf("%s took %d s%n", name,
TimeUnit.NANOSECONDS.toSeconds(stopwatch.getElapsedTimeNs()));
}
}

View file

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

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import jdk.test.failurehandler.action.ActionHelper;
import jdk.test.failurehandler.value.InvalidValueException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.util.Properties;
public final class GathererFactory {
private final Path workdir;
private final Path[] jdks;
private final PrintWriter log;
private final String osName;
public GathererFactory(String osName, Path workdir, PrintWriter log, Path... jdks) {
this.osName = osName;
this.workdir = workdir;
this.log = log;
this.jdks = jdks;
}
public EnvironmentInfoGatherer getEnvironmentInfoGatherer() {
return create();
}
public ProcessInfoGatherer getProcessInfoGatherer() {
return create();
}
public CoreInfoGatherer getCoreInfoGatherer() {
return create();
}
private ToolKit create() {
Properties osProperty = Utils.getProperties(osName);
try {
ActionHelper helper = new ActionHelper(workdir, "config", osProperty, jdks);
// os-specific action set must be last, b/c they can kill the process
return new ToolKit(helper, log, "common", osName);
} catch (InvalidValueException e) {
throw new IllegalStateException("can't create tool kit", e);
}
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
public class HtmlPage implements AutoCloseable {
static final String STYLE_SHEET_FILENAME = "failure-handler-style.css";
static final String SCRIPT_FILENAME = "failure-handler-script.js";
private final PrintWriter writer;
private final HtmlSection rootSection;
/**
* Constructs a {@code HtmlPage}
*
* @param dir The directory into which the HTML file and related resources will be created
* @param htmlFileName The HTML file name
* @param append if {@code true} then the content will be appended to the file represented
* by the {@code htmlFileName}, else the {@code htmlFileName} will be overwritten
* with the new content
* @throws IllegalArgumentException if {@code dir} is not a directory or if the
* {@code htmlFileName} is {@linkplain String#isBlank() blank}
* @throws IOException if there is an error constructing file resource(s) for this HTML page
*/
public HtmlPage(final Path dir, final String htmlFileName, final boolean append)
throws IOException {
Objects.requireNonNull(dir, "directory cannot be null");
Objects.requireNonNull(htmlFileName, "HTML file name cannot be null");
if (!Files.isDirectory(dir)) {
throw new IllegalArgumentException(dir + " is not a directory");
}
if (htmlFileName.isBlank()) {
throw new IllegalArgumentException("HTML file name cannot be blank");
}
final FileWriter fileWriter = new FileWriter(dir.resolve(htmlFileName).toFile(), append);
this.writer = new PrintWriter(fileWriter, true);
createScriptFile(dir);
createStyleSheetFile(dir);
rootSection = new HtmlSection(writer);
}
@Override
public void close() {
writer.close();
}
public HtmlSection getRootSection() {
return rootSection;
}
private static void createStyleSheetFile(final Path destDir) throws IOException {
final Path styleSheet = destDir.resolve(STYLE_SHEET_FILENAME);
if (Files.exists(styleSheet)) {
return;
}
final String content = """
div { display:none;}
""";
Files.writeString(styleSheet, content);
}
private static void createScriptFile(final Path destDir) throws IOException {
final Path script = destDir.resolve(SCRIPT_FILENAME);
if (Files.exists(script)) {
return;
}
final String content = """
function doShow(e) {
while (e != null) {
if (e.tagName == 'DIV') {
e.style.display = 'block';
}
e = e.parentNode;
}
}
function showHandler(event) {
elementId = this.dataset.show;
elementToShow = document.getElementById(elementId);
doShow(elementToShow);
}
function toggleHandler(event) {
toggleElementId = this.dataset.toggle;
elementToToggle = document.getElementById(toggleElementId);
d = elementToToggle.style.display;
if (d == 'block') {
elementToToggle.style.display = 'none';
} else {
doShow(elementToToggle);
}
}
function bodyLoadHandler() {
const index = location.href.indexOf("#");
if (index != -1) {
doShow(document.getElementById(location.href.substring(index + 1)));
}
// elements that require the "toggleHandler" function to be registered
// as an event handler for the onclick event
const requiringToggleHandler = document.querySelectorAll("[data-toggle]");
for (const e of requiringToggleHandler) {
e.addEventListener("click", toggleHandler);
}
// elements that require the "showHandler" function to be registered
// as an event handler for the onclick event
const requiringShowHandler = document.querySelectorAll("[data-show]");
for (const e of requiringShowHandler) {
e.addEventListener("click", showHandler);
}
}
// register a onload event handler
window.addEventListener("DOMContentLoaded", bodyLoadHandler);
""";
Files.writeString(script, content);
}
}

View file

@ -0,0 +1,220 @@
/*
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class HtmlSection {
protected final HtmlSection rootSection;
protected final String id;
protected final String name;
public PrintWriter getWriter() {
return textWriter;
}
protected final PrintWriter pw;
protected final PrintWriter textWriter;
protected boolean closed;
private HtmlSection child;
public HtmlSection(PrintWriter pw) {
this(pw, "", null, null);
}
private HtmlSection(PrintWriter pw, String id, String name, HtmlSection rootSection) {
this.pw = pw;
textWriter = new PrintWriter(new HtmlFilterWriter(pw), true);
this.id = id;
this.name = name;
child = null;
// main
if (rootSection == null) {
this.rootSection = this;
this.pw.println("<html>");
this.pw.println("<head>");
this.pw.println(
"<link href=\"" + HtmlPage.STYLE_SHEET_FILENAME + "\" rel=\"stylesheet\" type=\"text/css\" />");
this.pw.println(
"<script src=\"" + HtmlPage.SCRIPT_FILENAME + "\" type=\"text/javascript\" ></script>");
this.pw.println("</head>");
this.pw.println("<body>");
} else {
this.rootSection = rootSection;
this.pw.print("<ul>");
}
}
public HtmlSection createChildren(String section) {
if (child != null) {
if (child.name.equals(section)) {
return child;
}
child.close();
}
child = new SubSection(this, section, rootSection);
return child;
}
protected final void removeChild(HtmlSection child) {
if (this.child == child) {
this.child = null;
}
}
public void close() {
closeChild();
if (closed) {
return;
}
closed = true;
if (rootSection == this) {
pw.println("</body>");
pw.println("</html>");
pw.close();
} else {
pw.println("</ul>");
}
}
protected final void closeChild() {
if (child != null) {
child.close();
child = null;
}
}
public void link(HtmlSection section, String child, String name) {
String path = section.id;
if (path.isEmpty()) {
path = child;
} else if (child != null) {
path = String.format("%s.%s", path, child);
}
pw.printf("<a href=\"#%1$s\" data-show=\"%1$s\" >%2$s</a>%n",
path, name);
}
/**
* Creates a {@code <a href></a>} link with {@code targetAddress} being the value for {@code href}
* and the {@code linkText} being the text for the link.
*
* @param targetAddress the target address
* @param linkText the text for the link
*/
public void createLink(String targetAddress, String linkText) {
pw.printf("<a href=\"%1$s\">%2$s</a>%n", targetAddress, linkText);
}
public HtmlSection createChildren(String[] sections) {
int i = 0;
int n = sections.length;
HtmlSection current = this;
for (; i < n && current.child != null;
++i, current = current.child) {
if (!sections[i].equals(current.child.name)) {
break;
}
}
for (; i < n; ++i) {
current = current.createChildren(sections[i]);
}
return current;
}
private static class SubSection extends HtmlSection {
private final HtmlSection parent;
public SubSection(HtmlSection parent, String name,
HtmlSection rootSection) {
super(parent.pw,
parent.id.isEmpty()
? name
: String.format("%s.%s", parent.id, name),
name, rootSection);
this.parent = parent;
pw.printf("<li><a name='%1$s'/><a href='#%1$s' data-toggle=\"%1$s\" >%2$s</a><div id='%1$s'><code><pre>",
id, name);
}
@Override
public void close() {
closeChild();
if (closed) {
return;
}
pw.print("</pre></code></div></li><!-- " + id + "-->");
parent.removeChild(this);
super.close();
}
}
private static class HtmlFilterWriter extends FilterWriter {
public HtmlFilterWriter(PrintWriter pw) {
super(pw);
}
@Override
public void write(int c) throws IOException {
switch (c) {
case '<':
super.write("&lt;", 0, 4);
break;
case '>':
super.write("&gt;", 0, 4);
break;
case '"':
super.write("&quot;", 0, 5);
break;
case '&':
super.write("&amp;", 0, 4);
break;
default:
super.write(c);
}
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
for (int i = off; i < len; ++i){
write(cbuf[i]);
}
}
@Override
public void write(String str, int off, int len) throws IOException {
for (int i = off; i < len; ++i){
write(str.charAt(i));
}
}
}
}

View file

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

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
public final class Stopwatch {
protected boolean isResultAvailable;
protected boolean isRunning;
private long startTimeNs;
private long stopTimeNs;
public Stopwatch() {
isResultAvailable = false;
}
/**
* Starts measuring time.
*/
public void start() {
startTimeNs = System.nanoTime();
isRunning = true;
}
/**
* Stops measuring time.
*/
public void stop() {
if (!isRunning) {
throw new IllegalStateException(" hasn't been started");
}
stopTimeNs = System.nanoTime();
isRunning = false;
isResultAvailable = true;
}
/**
* @return time in nanoseconds measured between
* calls of {@link #start()} and {@link #stop()} methods.
*
* @throws IllegalStateException if called without preceding
* {@link #start()} {@link #stop()} method
*/
public long getElapsedTimeNs() {
if (isRunning) {
throw new IllegalStateException("hasn't been stopped");
}
if (!isResultAvailable) {
throw new IllegalStateException("was not run");
}
return stopTimeNs - startTimeNs;
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import jdk.test.failurehandler.action.ActionSet;
import jdk.test.failurehandler.action.ActionHelper;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Deque;
import java.util.zip.GZIPInputStream;
public class ToolKit implements EnvironmentInfoGatherer, ProcessInfoGatherer, CoreInfoGatherer {
private final List<ActionSet> actions = new ArrayList<>();
private final ActionHelper helper;
private final PrintWriter log;
public ToolKit(ActionHelper helper, PrintWriter log, String... names) {
this.helper = helper;
this.log = log;
for (String name : names) {
actions.add(new ActionSet(helper, log, name));
}
}
@Override
public void gatherEnvironmentInfo(HtmlSection section) {
for (ActionSet set : actions) {
set.gatherEnvironmentInfo(section);
}
}
@Override
public void gatherCoreInfo(HtmlSection section, Path core) {
if (core.getFileName().toString().endsWith(".gz")) {
Path unpackedCore = Path.of(core.toString().replace(".gz", ""));
try (GZIPInputStream gzis = new GZIPInputStream(Files.newInputStream(core))) {
Files.copy(gzis, unpackedCore);
for (ActionSet set : actions) {
set.gatherCoreInfo(section, unpackedCore);
}
Files.delete(unpackedCore);
} catch (IOException ioe) {
log.printf("Unexpected exception whilc opening %s", core.getFileName().toString());
ioe.printStackTrace(log);
}
} else {
for (ActionSet set : actions) {
set.gatherCoreInfo(section, core);
}
}
}
@Override
public void gatherProcessInfo(HtmlSection section, long pid) {
// as some of actions can kill a process, we need to get children of all
// test process first, and run the actions starting from the leaves
// and going up by the process tree
Deque<Long> orderedPids = new LinkedList<>();
Queue<Long> testPids = new LinkedList<>();
testPids.add(pid);
HtmlSection ptreeSection = section.createChildren("test_processes");
for (Long p = testPids.poll(); p != null; p = testPids.poll()) {
orderedPids.addFirst(p);
List<Long> children = helper.getChildren(ptreeSection, p);
if (!children.isEmpty()) {
HtmlSection s = ptreeSection.createChildren("" + p);
for (Long c : children) {
s.link(section, c.toString(), c.toString());
}
testPids.addAll(children);
}
}
for (Long p : orderedPids) {
for (ActionSet set : actions) {
set.gatherProcessInfo(section, p);
}
}
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.Properties;
public final class Utils {
private static final int BUFFER_LENGTH = 1024;
public static String prependPrefix(String prefix, String name) {
return (prefix == null || prefix.isEmpty())
? name
: (name == null || name.isEmpty())
? prefix
: String.format("%s.%s", prefix, name);
}
public static void copyStream(InputStream in, OutputStream out)
throws IOException {
int n;
byte[] buffer = new byte[BUFFER_LENGTH];
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
}
out.flush();
}
public static void copyStream(Reader in, Writer out)
throws IOException {
int n;
char[] buffer = new char[BUFFER_LENGTH];
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
}
out.flush();
}
public static Properties getProperties(String name) {
Properties properties = new Properties();
String resourceName = String.format(
"/%s.%s", name.toLowerCase(), "properties");
InputStream stream = Utils.class.getResourceAsStream(resourceName);
if (stream == null) {
throw new IllegalStateException(String.format(
"resource '%s' doesn't exist%n", resourceName));
}
try {
try {
properties.load(stream);
} finally {
stream.close();
}
} catch (IOException e) {
throw new IllegalStateException(String.format(
"can't read resource '%s' : %s%n",
resourceName, e.getMessage()), e);
}
return properties;
}
private Utils() { }
}

View file

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

View file

@ -0,0 +1,404 @@
/*
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.action;
import jdk.test.failurehandler.value.InvalidValueException;
import jdk.test.failurehandler.value.Value;
import jdk.test.failurehandler.value.ValueHandler;
import jdk.test.failurehandler.HtmlSection;
import jdk.test.failurehandler.Stopwatch;
import jdk.test.failurehandler.Utils;
import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
public class ActionHelper {
private final Path workDir;
@Value(name = "execSuffix")
private String executableSuffix = "";
private Path[] paths;
private final PatternAction getChildren;
public ActionHelper(Path workDir, String prefix, Properties properties,
Path... jdks) throws InvalidValueException {
this.workDir = workDir.toAbsolutePath();
getChildren = new PatternAction(null,
Utils.prependPrefix(prefix, "getChildren"), properties);
ValueHandler.apply(this, properties, prefix);
String[] pathStrings = System.getenv("PATH").split(File.pathSeparator);
paths = new Path[pathStrings.length];
for (int i = 0; i < paths.length; ++i) {
paths[i] = Paths.get(pathStrings[i]);
}
addJdks(jdks);
}
public List<Long> getChildren(HtmlSection section, long pid) {
String pidStr = "" + pid;
ProcessBuilder pb = getChildren.prepareProcess(section, this, pidStr);
HtmlSection childrenSection = getChildren.getSection(section);
PrintWriter log = childrenSection.getWriter();
CharArrayWriter writer = new CharArrayWriter();
ExitCode code = run(childrenSection, log, writer, pb, getChildren.getParameters());
Reader output = new CharArrayReader(writer.toCharArray());
if (!ExitCode.OK.equals(code)) {
log.println("WARNING: get children pids action failed");
try {
Utils.copyStream(output, log);
} catch (IOException e) {
e.printStackTrace(log);
}
return Collections.emptyList();
}
List<Long> result = new ArrayList<>();
try {
try (BufferedReader reader = new BufferedReader(output)) {
String line;
while ((line = reader.readLine()) != null) {
String value = line.trim();
if (value.isEmpty()) {
// ignore empty lines
continue;
}
try {
result.add(Long.valueOf(value));
} catch (NumberFormatException e) {
log.printf("WARNING: can't parse child pid %s : %s%n",
line, e.getMessage());
e.printStackTrace(log);
}
}
}
} catch (IOException e) {
e.printStackTrace(log);
}
return result;
}
public ProcessBuilder prepareProcess(PrintWriter log, String app,
String... args) {
File appBin = findApp(app);
if (appBin == null) {
log.printf("ERROR: can't find %s in %s.%n",
app, Arrays.toString(paths));
return null;
}
List<String> command = new ArrayList<>(args.length + 1);
command.add(appBin.toString());
Collections.addAll(command, args);
return new ProcessBuilder()
.command(command)
.directory(workDir.toFile());
}
public File findApp(String app) {
String name = app + executableSuffix;
for (Path pathElem : paths) {
File result = pathElem.resolve(name).toFile();
if (result.exists()) {
return result;
}
}
return null;
}
private void addJdks(Path[] jdkPaths) {
if (jdkPaths != null && jdkPaths.length != 0) {
Path[] result = new Path[jdkPaths.length + paths.length];
for (int i = 0; i < jdkPaths.length; ++i) {
result[i] = jdkPaths[i].resolve("bin");
}
System.arraycopy(paths, 0, result, jdkPaths.length, paths.length);
paths = result;
}
}
private ExitCode run(HtmlSection section, PrintWriter log, Writer out, ProcessBuilder pb,
ActionParameters params) {
char[] lineChars = new char[40];
Arrays.fill(lineChars, '-');
String line = new String(lineChars);
Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
log.printf("%s%n[%tF %<tT] %s timeout=%s in %s%n%1$s%n", line, new Date(), pb.command(), params.timeout, pb.directory());
Process process;
KillerTask killer;
ExitCode result = ExitCode.NEVER_STARTED;
try {
process = pb.start();
killer = new KillerTask(process);
killer.schedule(params.timeout);
Utils.copyStream(new InputStreamReader(process.getInputStream()),
out);
try {
result = new ExitCode(process.waitFor());
} catch (InterruptedException e) {
log.println("WARNING: interrupted when waiting for the tool:%n");
e.printStackTrace(log);
} finally {
killer.cancel();
}
if (killer.hasTimedOut()) {
log.printf(
"WARNING: tool timed out: killed process after %d ms%n",
params.timeout);
result = ExitCode.TIMED_OUT;
}
} catch (IOException e) {
log.printf("WARNING: caught IOException while running tool%n");
e.printStackTrace(log);
result = ExitCode.LAUNCH_ERROR;
}
stopwatch.stop();
log.printf("%s%n[%tF %<tT] exit code: %d time: %d ms%n%1$s%n",
line, new Date(), result.value,
TimeUnit.NANOSECONDS.toMillis(stopwatch.getElapsedTimeNs()));
// upon successful completion of the action, generate links to any successArtifacts
// that have been declared for this action
if (ExitCode.OK.equals(result) && params.successArtifacts != null) {
final StringTokenizer t = new StringTokenizer(params.successArtifacts, ",");
while (t.hasMoreTokens()) {
final String artifactPath = t.nextToken().trim();
if (artifactPath.isEmpty()) {
continue;
}
// create a link to the artifact
section.createLink(artifactPath, artifactPath);
}
}
return result;
}
public void runPatternAction(SimpleAction action, HtmlSection section) {
if (action != null) {
HtmlSection subSection = action.getSection(section);
PrintWriter log = subSection.getWriter();
ProcessBuilder pb = action.prepareProcess(log, this);
exec(subSection, pb, action.getParameters());
}
}
public void runPatternAction(PatternAction action, HtmlSection section,
String value) {
if (action != null) {
ProcessBuilder pb = action.prepareProcess(section, this, value);
HtmlSection subSection = action.getSection(section);
exec(subSection, pb, action.getParameters());
}
}
public boolean isJava(long pid, PrintWriter log) {
ProcessBuilder pb = prepareProcess(log, "jps", "-q");
if (pb == null) {
return false;
}
pb.redirectErrorStream(true);
boolean result = false;
String pidStr = "" + pid;
try {
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null){
if (pidStr.equals(line)) {
result = true;
}
}
}
process.waitFor();
} catch (IOException e) {
log.printf("WARNING: can't run jps : %s%n", e.getMessage());
e.printStackTrace(log);
} catch (InterruptedException e) {
log.printf("WARNING: interrupted%n");
e.printStackTrace(log);
}
return result;
}
private static class KillerTask extends TimerTask {
private static final Timer WATCHDOG = new Timer("WATCHDOG", true);
private final Process process;
private boolean timedOut;
public KillerTask(Process process) {
this.process = process;
}
public void run() {
try {
process.exitValue();
} catch (IllegalThreadStateException e) {
process.destroyForcibly();
timedOut = true;
}
}
public boolean hasTimedOut() {
return timedOut;
}
public void schedule(long timeout) {
if (timeout > 0) {
WATCHDOG.schedule(this, timeout);
}
}
}
private void exec(HtmlSection section, ProcessBuilder process,
ActionParameters params) {
if (process == null) {
return;
}
PrintWriter sectionWriter = section.getWriter();
if (params.repeat > 1) {
// hold on to the original command and successArtifacts values which potentially
// contain the %iterCount token, since we need to replace it with different value
// on each iteration
String originalSuccessArtifacts = params.successArtifacts;
List<String> originalCommand = process.command();
for (int i = 0, n = params.repeat; i < n; ++i) {
HtmlSection iteration = section.createChildren(
String.format("iteration_%d", i));
PrintWriter writer = iteration.getWriter();
// use the original values with the token (if any)
params.successArtifacts = originalSuccessArtifacts;
process.command(originalCommand);
// replace the %iterCount token (if any)
prepareIteration(i, process, params);
ExitCode exitCode = run(section, writer, writer, process, params);
if (params.stopOnError && !ExitCode.OK.equals(exitCode)) {
sectionWriter.printf(
"ERROR: non zero exit code[%d] -- break.",
exitCode.value);
break;
}
// sleep, if this is not the last iteration
if (i < n - 1) {
try {
Thread.sleep(params.pause);
} catch (InterruptedException e) {
sectionWriter.printf(
"WARNING: interrupted while sleeping between invocations");
e.printStackTrace(sectionWriter);
}
}
}
} else {
prepareIteration(0, process, params);
run(section, section.getWriter(), section.getWriter(), process, params);
}
}
// replaces the occurrences of %iterCount from the process builder command/arguments
// and the action params' "successArtifacts" paths, with the iteration count
private void prepareIteration(int iterationCount, ProcessBuilder pb,
ActionParameters actionParams) {
List<String> command = new ArrayList<>();
for (String arg : pb.command()) {
arg = arg.replaceAll("%iterCount", String.valueOf(iterationCount)) ;
command.add(arg);
}
pb.command(command);
String successArtifacts = actionParams.successArtifacts;
if (successArtifacts != null) {
actionParams.successArtifacts = successArtifacts.replaceAll("%iterCount",
String.valueOf(iterationCount));
}
}
/**
* Special values for prepareProcess exit code.
*
* <p>Can we clash with normal codes?
* On Linux, only [0..255] are returned.
* On Windows, prepareProcess exit codes are stored in unsigned int.
* On MacOSX no limits (except it should fit C int type)
* are defined in the exit() man pages.
*/
private static class ExitCode {
/** Process exits gracefully */
public static final ExitCode OK = new ExitCode(0);
/** Error launching prepareProcess */
public static final ExitCode LAUNCH_ERROR = new ExitCode(-1);
/** Application prepareProcess has been killed by watchdog due to timeout */
public static final ExitCode TIMED_OUT = new ExitCode(-2);
/** Application prepareProcess has never been started due to program logic */
public static final ExitCode NEVER_STARTED = new ExitCode(-3);
public final int value;
private ExitCode(int value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ExitCode exitCode = (ExitCode) o;
return value == exitCode.value;
}
@Override
public int hashCode() {
return value;
}
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.action;
import jdk.test.failurehandler.value.DefaultValue;
import jdk.test.failurehandler.value.Value;
public class ActionParameters {
@Value (name = "repeat")
@DefaultValue (value = "1")
public int repeat = 1;
@Value (name = "pause")
@DefaultValue (value = "500")
public long pause = 500;
@Value (name = "stopOnError")
@DefaultValue (value = "false")
public boolean stopOnError = false;
@Value (name = "timeout")
@DefaultValue (value = "" + 20_000L)
public long timeout = -1L;
@Value (name = "successArtifacts")
@DefaultValue (value = "")
public String successArtifacts = "";
public ActionParameters() { }
}

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.action;
import jdk.test.failurehandler.CoreInfoGatherer;
import jdk.test.failurehandler.ProcessInfoGatherer;
import jdk.test.failurehandler.EnvironmentInfoGatherer;
import jdk.test.failurehandler.HtmlSection;
import jdk.test.failurehandler.Utils;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.zip.GZIPInputStream;
public class ActionSet implements ProcessInfoGatherer, EnvironmentInfoGatherer, CoreInfoGatherer {
private static final String ENVIRONMENT_PROPERTY = "environment";
private static final String ON_PID_PROPERTY = "onTimeout";
private static final String CORES_PROPERTY = "cores";
private final ActionHelper helper;
public String getName() {
return name;
}
private final String name;
private final List<SimpleAction> environmentActions;
private final List<PatternAction> processActions;
private final List<PatternAction> coreActions;
public ActionSet(ActionHelper helper, PrintWriter log, String name) {
this.helper = helper;
this.name = name;
Properties p = Utils.getProperties(name);
environmentActions = getSimpleActions(log, p, ENVIRONMENT_PROPERTY);
processActions = getPatternActions(log, p, ON_PID_PROPERTY);
coreActions = getPatternActions(log, p, CORES_PROPERTY);
}
private List<SimpleAction> getSimpleActions(PrintWriter log, Properties p,
String key) {
String[] tools = getTools(log, p, key);
List<SimpleAction> result = new ArrayList<>(tools.length);
for (String tool : tools) {
try {
SimpleAction action = new SimpleAction(
Utils.prependPrefix(name, tool), tool, p);
result.add(action);
} catch (Exception e) {
log.printf("ERROR: %s cannot be created : %s %n",
tool, e.getMessage());
e.printStackTrace(log);
}
}
return result;
}
private List<PatternAction> getPatternActions(PrintWriter log,
Properties p, String key) {
String[] tools = getTools(log, p, key);
List<PatternAction> result = new ArrayList<>(tools.length);
for (String tool : tools) {
try {
PatternAction action = new PatternAction(
Utils.prependPrefix(name, tool), tool, p);
result.add(action);
} catch (Exception e) {
log.printf("ERROR: %s cannot be created : %s %n",
tool, e.getMessage());
e.printStackTrace(log);
}
}
return result;
}
private String[] getTools(PrintWriter writer, Properties p, String key) {
String value = p.getProperty(key);
if (value == null) {
writer.printf("ERROR: '%s' property is not set%n", key);
return new String[]{};
}
if (value.isEmpty()) {
return new String[]{};
}
return value.split(" ");
}
@Override
public void gatherProcessInfo(HtmlSection section, long pid) {
String pidStr = "" + pid;
for (PatternAction action : processActions) {
if (action.isJavaOnly()) {
if (helper.isJava(pid, section.getWriter())) {
helper.runPatternAction(action, section, pidStr);
}
} else {
helper.runPatternAction(action, section, pidStr);
}
}
}
@Override
public void gatherEnvironmentInfo(HtmlSection section) {
for (SimpleAction action : environmentActions) {
helper.runPatternAction(action, section);
}
}
@Override
public void gatherCoreInfo(HtmlSection section, Path core) {
for (PatternAction action : coreActions) {
helper.runPatternAction(action, section, core.toString());
}
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.action;
import jdk.test.failurehandler.value.InvalidValueException;
import jdk.test.failurehandler.HtmlSection;
import jdk.test.failurehandler.value.Value;
import jdk.test.failurehandler.value.ValueHandler;
import java.util.Properties;
public class PatternAction implements Action {
@Value(name = "pattern")
private String pattern = null;
private final SimpleAction action;
private final String[] originalArgs;
private final String originalSuccessArtifacts;
public PatternAction(String id, Properties properties)
throws InvalidValueException {
this(id, id, properties);
}
public PatternAction(String name, String id, Properties properties)
throws InvalidValueException {
action = new SimpleAction(name != null ? ("pattern." + name) : "pattern", id, properties);
ValueHandler.apply(this, properties, id);
originalArgs = action.args.clone();
ActionParameters params = action.getParameters();
// just like the "args" the "successArtifacts" param can also contain pattern that
// this PatternAction will (sometimes repeatedly) replace, so we keep track of
// the original (un-replaced text)
originalSuccessArtifacts = params == null ? null : params.successArtifacts;
}
public ProcessBuilder prepareProcess(HtmlSection section,
ActionHelper helper, String value) {
action.sections[0] = value;
section = getSection(section);
String[] args = action.args;
System.arraycopy(originalArgs, 0, args, 0, originalArgs.length);
for (int i = 0, n = args.length; i < n; ++i) {
args[i] = args[i].replace(pattern, value) ;
}
for (int i = 0, n = args.length; i < n; ++i) {
args[i] = args[i].replace("%java", helper.findApp("java").getAbsolutePath());
}
// replace occurrences of the pattern in the "successArtifacts" param
if (originalSuccessArtifacts != null) {
action.getParameters().successArtifacts = originalSuccessArtifacts.replaceAll(pattern,
value);
}
return action.prepareProcess(section.getWriter(), helper);
}
@Override
public HtmlSection getSection(HtmlSection section) {
return action.getSection(section);
}
@Override
public ActionParameters getParameters() {
return action.getParameters();
}
@Override
public boolean isJavaOnly() {
return action.isJavaOnly();
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.action;
import jdk.test.failurehandler.HtmlSection;
import jdk.test.failurehandler.value.InvalidValueException;
import jdk.test.failurehandler.value.SubValues;
import jdk.test.failurehandler.value.Value;
import jdk.test.failurehandler.value.ValueHandler;
import jdk.test.failurehandler.value.DefaultValue;
import java.io.PrintWriter;
import java.util.Properties;
public class SimpleAction implements Action {
/* package-private */ final String[] sections;
@Value(name = "javaOnly")
@DefaultValue(value = "false")
private boolean javaOnly = false;
@Value (name = "app")
private String app = null;
@Value (name = "args")
@DefaultValue (value = "")
/* package-private */ String[] args = new String[]{};
@SubValues(prefix = "params")
private final ActionParameters params;
public SimpleAction(String id, Properties properties)
throws InvalidValueException {
this(id, id, properties);
}
public SimpleAction(String name, String id, Properties properties)
throws InvalidValueException {
sections = name.split("\\.");
this.params = new ActionParameters();
ValueHandler.apply(this, properties, id);
}
public ProcessBuilder prepareProcess(PrintWriter log, ActionHelper helper) {
ProcessBuilder process = helper.prepareProcess(log, app, args);
if (process != null) {
process.redirectErrorStream(true);
}
return process;
}
@Override
public boolean isJavaOnly() {
return javaOnly;
}
@Override
public HtmlSection getSection(HtmlSection section) {
return section.createChildren(sections);
}
@Override
public ActionParameters getParameters() {
return params;
}
}

View file

@ -0,0 +1,154 @@
/*
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.jtreg;
import com.sun.javatest.Harness;
import com.sun.javatest.Parameters;
import com.sun.javatest.TestResult;
import com.sun.javatest.regtest.config.RegressionParameters;
import jdk.test.failurehandler.*;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Stream;
/**
* The jtreg test execution observer, which gathers info about
* system and dumps it to a file.
*/
public class GatherDiagnosticInfoObserver implements Harness.Observer {
public static final String LOG_FILENAME = "environment.log";
public static final String ENVIRONMENT_OUTPUT = "environment.html";
public static final String CORES_OUTPUT = "cores.html";
private Path compileJdk;
private Path testJdk;
/*
* The harness calls this method after each test.
*/
@Override
public void finishedTest(TestResult tr) {
if (!tr.getStatus().isError() && !tr.getStatus().isFailed()) {
return;
}
String jtrFile = tr.getFile().toString();
final Path workDir = Paths.get(
jtrFile.substring(0, jtrFile.lastIndexOf('.')));
workDir.toFile().mkdir();
String name = getClass().getName();
PrintWriter log1;
boolean needClose = false;
try {
log1 = new PrintWriter(new FileWriter(
workDir.resolve(LOG_FILENAME).toFile(), true), true);
needClose = true;
} catch (IOException e) {
log1 = new PrintWriter(System.out);
log1.printf("ERROR: %s cannot open log file %s", name,
LOG_FILENAME);
e.printStackTrace(log1);
}
final PrintWriter log = log1;
try {
log.printf("%s ---%n", name);
GathererFactory gathererFactory = new GathererFactory(
OS.current().family, workDir, log,
testJdk, compileJdk);
gatherEnvInfo(workDir, name, log,
gathererFactory.getEnvironmentInfoGatherer());
// generate a cores.html file after parsing the core dump files (if any)
List<Path> coreFiles;
try (Stream<Path> paths = Files.walk(workDir)) {
coreFiles = paths.filter(Files::isRegularFile)
.filter(f -> (f.getFileName().toString().contains("core")
|| f.getFileName().toString().contains("mdmp")))
.toList();
}
gatherCoreInfo(workDir, name, coreFiles, log, gathererFactory.getCoreInfoGatherer());
} catch (Throwable e) {
log.printf("ERROR: exception in observer %s:", name);
e.printStackTrace(log);
} finally {
log.printf("--- %s%n", name);
if (needClose) {
log.close();
} else {
log.flush();
}
}
}
private void gatherCoreInfo(Path workDir, String name, List<Path> coreFiles,
PrintWriter log, CoreInfoGatherer gatherer) {
if (coreFiles.isEmpty()) {
return;
}
try (HtmlPage html = new HtmlPage(workDir, CORES_OUTPUT, true)) {
try (ElapsedTimePrinter timePrinter
= new ElapsedTimePrinter(new Stopwatch(), name, log)) {
// gather information from the contents of each core file
for (Path coreFile : coreFiles) {
gatherer.gatherCoreInfo(html.getRootSection(), coreFile);
}
}
} catch (Throwable e) {
log.printf("ERROR: exception in %s observer while gathering information from"
+ " core dump file", name);
e.printStackTrace(log);
}
}
private void gatherEnvInfo(Path workDir, String name, PrintWriter log,
EnvironmentInfoGatherer gatherer) {
try (HtmlPage html = new HtmlPage(workDir, ENVIRONMENT_OUTPUT, true)) {
try (ElapsedTimePrinter timePrinter
= new ElapsedTimePrinter(new Stopwatch(), name, log)) {
gatherer.gatherEnvironmentInfo(html.getRootSection());
}
} catch (Throwable e) {
log.printf("ERROR: exception in observer on getting environment "
+ "information %s:", name);
e.printStackTrace(log);
}
}
/*
* The harness calls this method one time per run, not per test.
*/
@Override
public void startingTestRun(Parameters params) {
RegressionParameters rp = (RegressionParameters) params;
compileJdk = rp.getCompileJDK().getAbsoluteFile().toPath();
testJdk = rp.getTestJDK().getAbsoluteFile().toPath();
}
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.jtreg;
import com.sun.javatest.regtest.TimeoutHandler;
import jdk.test.failurehandler.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
/**
* A timeout handler for jtreg, which gathers information about the timed out
* process and its children.
*/
public class GatherProcessInfoTimeoutHandler extends TimeoutHandler {
private static final String LOG_FILENAME = "processes.log";
private static final String OUTPUT_FILENAME = "processes.html";
public GatherProcessInfoTimeoutHandler(PrintWriter jtregLog, File outputDir,
File testJdk) {
super(jtregLog, outputDir, testJdk);
}
/**
* Runs various actions for jtreg timeout handler.
*
* <p>Please see method code for the actions.
*/
@Override
protected void runActions(Process process, long pid)
throws InterruptedException {
Path workDir = outputDir.toPath();
String name = getClass().getName();
PrintWriter actionsLog;
try {
// try to open a separate file for action log
actionsLog = new PrintWriter(new FileWriter(
workDir.resolve(LOG_FILENAME).toFile(), true), true);
} catch (IOException e) {
// use jtreg log as a fallback
actionsLog = log;
actionsLog.printf("ERROR: %s cannot open log file %s : %s", name,
LOG_FILENAME, e.getMessage());
}
try {
actionsLog.printf("%s ---%n", name);
runGatherer(name, actionsLog, pid);
} finally {
actionsLog.printf("--- %s%n", name);
// don't close jtreg log
if (actionsLog != log) {
actionsLog.close();
} else {
log.flush();
}
}
}
private void runGatherer(String name, PrintWriter log, long pid) {
Path workDir = outputDir.toPath();
try (HtmlPage html = new HtmlPage(workDir, OUTPUT_FILENAME, true)) {
ProcessInfoGatherer gatherer = new GathererFactory(
OS.current().family,
workDir, log, testJdk.toPath()).getProcessInfoGatherer();
try (ElapsedTimePrinter timePrinter
= new ElapsedTimePrinter(new Stopwatch(), name, log)) {
gatherer.gatherProcessInfo(html.getRootSection(), pid);
}
} catch (Throwable e) {
log.printf("ERROR: exception in timeout handler %s:", name);
e.printStackTrace(log);
}
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.jtreg;
// Stripped down version of jtreg internal class com.sun.javatest.regtest.config.OS
class OS {
public final String family;
private static OS current;
public static OS current() {
if (current == null) {
String name = System.getProperty("os.name");
current = new OS(name);
}
return current;
}
private OS(String name) {
if (name.startsWith("AIX")) {
family = "aix";
} else if (name.startsWith("Linux")) {
family = "linux";
} else if (name.startsWith("Mac") || name.startsWith("Darwin")) {
family = "mac";
} else if (name.startsWith("Windows")) {
family = "windows";
} else {
// use first word of name
family = name.replaceFirst("^([^ ]+).*", "$1");
}
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import java.lang.reflect.Array;
import java.util.Objects;
public class ArrayParser implements ValueParser {
private final ValueParser parser;
public ArrayParser(ValueParser parser) {
Objects.requireNonNull(parser);
this.parser = parser;
}
@Override
public Object parse(Class<?> type, String value, String delimiter) {
Class<?> component = type.getComponentType();
if (component.isArray()) {
throw new IllegalArgumentException(
"multidimensional array fields aren't supported");
}
String[] values = (value == null || value.isEmpty())
? new String[]{}
: value.split(delimiter);
Object result = Array.newInstance(component, values.length);
for (int i = 0, n = values.length; i < n; ++i) {
Array.set(result, i, parser.parse(component, values[i], delimiter));
}
return result;
}
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import java.util.HashMap;
import java.util.Map;
public class DefaultParser implements ValueParser {
private static final Map<Class<?>, BasicParser> PARSERS = new HashMap<>();
static {
BasicParser.init();
}
@Override
public Object parse(Class<?> type, String value, String s) {
if (type.isArray()) {
return new ArrayParser(this).parse(type, value, s);
}
ValueParser parser = PARSERS.get(type);
if (parser == null) {
throw new IllegalArgumentException("can't find parser for "
+ type.getName());
}
return parser.parse(type, value, s);
}
private static enum BasicParser implements ValueParser {
BOOL(boolean.class, Boolean.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Boolean.valueOf(value);
}
},
BYTE(byte.class, Byte.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Byte.decode(value);
}
},
CHAR(char.class, Character.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
if (value.length() != 1) {
throw new IllegalArgumentException(
String.format("can't cast %s to char", value));
}
return value.charAt(0);
}
},
SHORT(short.class, Short.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Short.decode(value);
}
},
INT(int.class, Integer.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Integer.decode(value);
}
},
LONG(long.class, Long.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Long.decode(value);
}
},
FLOAT(float.class, Float.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Float.parseFloat(value);
}
},
DOUBLE(double.class, Double.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return Double.parseDouble(value);
}
},
STRING(String.class, Object.class) {
@Override
public Object parse(Class<?> type, String value, String s) {
return value;
}
};
private BasicParser(Class<?>... classes) {
for (Class<?> aClass : classes) {
DefaultParser.PARSERS.put(aClass, this);
}
}
private static void init() {
// no-op used to provoke <cinit>
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import java.io.File;
public class PathValueParser implements ValueParser {
@Override
public Object parse(Class<?> type, String value, String delimiter) {
if (type.isArray()) {
return new ArrayParser(this).parse(type, value, delimiter);
}
return new File(value).toPath();
}
}

View file

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

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface Value {
String name();
Class<? extends ValueParser> parser() default DefaultParser.class;
}

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import jdk.test.failurehandler.Utils;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Objects;
import java.util.Properties;
public final class ValueHandler {
public static <T> void apply(T object, Properties properties,
String prefix) throws InvalidValueException {
Objects.requireNonNull(object, "object cannot be null");
Objects.requireNonNull(properties, "properties cannot be null");
Class<?> aClass = object.getClass();
while (aClass != null) {
for (Field field : aClass.getDeclaredFields()) {
Value p = field.getAnnotation(Value.class);
if (p != null) {
applyToField(p, object, field, properties, prefix);
} else {
SubValues sub
= field.getAnnotation(SubValues.class);
if (sub != null) {
getAccess(field);
try {
apply(field.get(object), properties,
Utils.prependPrefix(prefix, sub.prefix()));
} catch (IllegalAccessException e) {
throw new InvalidValueException(String.format(
"can't apply sub properties to %s.",
field.getName()));
}
}
}
}
aClass = aClass.getSuperclass();
}
}
private static void applyToField(Value property, Object object,
Field field, Properties properties, String prefix)
throws InvalidValueException {
getAccess(field);
if (Modifier.isFinal(field.getModifiers())) {
throw new InvalidValueException(
String.format("field '%s' is final", field));
}
String name = Utils.prependPrefix(prefix, property.name());
String value = getProperty(properties, prefix, property.name());
if (value == null) {
DefaultValue defaultValue
= field.getAnnotation(DefaultValue.class);
value = defaultValue == null ? null : defaultValue.value();
}
if (value == null) {
throw new InvalidValueException(String.format(
"can't set '%s', because properties don't have '%s'.",
field.getName(), name));
}
String delimiter = getProperty(properties,
Utils.prependPrefix(prefix, property.name()), "delimiter");
delimiter = delimiter == null ? " " : delimiter;
Class<? extends ValueParser> parserClass = property.parser();
try {
field.set(object, parserClass.getDeclaredConstructor().newInstance().parse(
field.getType(), value, delimiter));
} catch (ReflectiveOperationException | IllegalArgumentException e) {
throw new InvalidValueException(
String.format("can't set field '%s' : %s",
field.getName(), e.getMessage()), e);
}
}
private static String getProperty(Properties properties,
String prefix, String name) {
if (prefix == null || prefix.isEmpty()) {
return properties.getProperty(name);
}
int index = prefix.length();
do {
String value = properties.getProperty(
Utils.prependPrefix(prefix.substring(0, index), name));
if (value != null) {
return value;
}
index = prefix.lastIndexOf('.', index - 1);
} while (index > 0);
return properties.getProperty(name);
}
private static void getAccess(Field field) {
int modifiers = field.getModifiers();
if (!Modifier.isPublic(modifiers)) {
field.setAccessible(true);
}
}
}

View file

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

View file

@ -0,0 +1,97 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
pattern=%p
javaOnly=true
args=%p
################################################################################
# process info to gather
################################################################################
# It's important to retain the order of these actions and run the thread dump
# generating commands before the rest, to allow for capturing the test
# process' call stack as soon as the timeout has occurred. That reduces the chances
# of the test completing and thus missing crucial details from the thread dump
# while these timeout actions were being run.
onTimeout=\
thread_dump \
jinfo \
jcmd.compiler.codecache jcmd.compiler.codelist \
jcmd.compiler.queue \
jcmd.vm.classloader_stats jcmd.vm.stringtable \
jcmd.vm.symboltable jcmd.vm.uptime jcmd.vm.dynlibs \
jcmd.vm.system_properties jcmd.vm.info \
jcmd.gc.heap_info jcmd.gc.class_histogram jcmd.gc.finalizer_info jcmd.thread.dump_to_file jcmd.thread.vthread_scheduler \
jstack jhsdb.jstack.live.default jhsdb.jstack.live.mixed
jinfo.app=jinfo
jcmd.app=jcmd
jcmd.compiler.codecache.args=%p Compiler.codecache
jcmd.compiler.codelist.args=%p Compiler.codelist
jcmd.compiler.queue.args=%p Compiler.queue
jcmd.vm.classloader_stats.args=%p VM.classloader_stats
jcmd.vm.stringtable.args=%p VM.stringtable
jcmd.vm.symboltable.args=%p VM.symboltable
jcmd.vm.uptime.args=%p VM.uptime
jcmd.vm.dynlibs.args=%p VM.dynlibs
jcmd.vm.system_properties.args=%p VM.system_properties
jcmd.vm.info.args=%p VM.info
jcmd.gc.class_histogram.args=%p GC.class_histogram
jcmd.gc.finalizer_info.args=%p GC.finalizer_info
jcmd.gc.heap_info.args=%p GC.heap_info
jcmd.thread.dump_to_file.args=%p Thread.dump_to_file -format=json JavaThread.dump.%p.%iterCount
jcmd.thread.dump_to_file.params.repeat=6
jcmd.thread.dump_to_file.params.successArtifacts=JavaThread.dump.%p.%iterCount
jcmd.thread.vthread_scheduler.args=%p Thread.vthread_scheduler
# use jstack to generate one thread dump
thread_dump.app=jstack
thread_dump.args=-e -l %p
jstack.app=jstack
jstack.args=-e -l %p
jstack.params.repeat=5
jhsdb.app=jhsdb
jhsdb.jstack.live.default.args=jstack --pid %p
jhsdb.jstack.live.default.params.repeat=6
jhsdb.jstack.live.mixed.args=jstack --mixed --pid %p
jhsdb.jstack.live.mixed.params.repeat=6
cores=jhsdb.jstack.core.default jhsdb.jstack.core.mixed
# Assume that java standard laucher has been used
jhsdb.jstack.core.default.args=jstack --core %p --exe %java
jhsdb.jstack.core.mixed.args=jstack --mixed --core %p --exe %java
################################################################################
# environment info to gather
################################################################################
environment=jps
jps.app=jps
jps.args=-mlv
################################################################################

View file

@ -0,0 +1,155 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
config.execSuffix=
config.getChildren.pattern=%p
config.getChildren.app=ps
config.getChildren.args=--no-headers -o pid --ppid %p
################################################################################
# process info to gather
################################################################################
onTimeout=\
native.pmap.normal native.pmap.everything \
native.files native.locks \
native.stack native.core
################################################################################
native.pattern=%p
native.javaOnly=false
native.args=%p
native.pmap.app=pmap
native.pmap.normal.args=-p %p
native.pmap.everything.args=-XXp %p
native.files.app=lsof
native.files.args=-p %p
native.locks.app=lslocks
native.locks.args=-u --pid %p
native.stack.app=gdb
native.stack.args=--pid=%p\0-batch\0-ex\0info threads\0-ex\0thread apply all backtrace
native.stack.args.delimiter=\0
native.stack.params.repeat=6
# has to be the last command
native.core.app=bash
# The below trick was found on https://stackoverflow.com/a/41613532
native.core.args=-c\0kill -ABRT %p && tail --pid=%p -f /dev/null
native.core.args.delimiter=\0
native.core.timeout=600000
cores=native.gdb
native.gdb.app=gdb
# Assume that java standard laucher has been used
native.gdb.args=%java\0-c\0%p\0-batch\0-ex\0info threads\0-ex\0thread apply all backtrace
native.gdb.args.delimiter=\0
################################################################################
# environment info to gather
################################################################################
environment=\
users.current users.logged users.last \
disk \
env \
ulimit \
system.dmesg system.sysctl \
process.top process.ps \
memory.free memory.vmstat.default memory.vmstat.statistics \
memory.vmstat.slabinfo memory.vmstat.disk \
memory.proc_meminfo memory.proc_vmstat \
memory.thp \
files \
locks \
net.sockets net.statistics net.ifconfig net.hostsfile \
screenshot
################################################################################
users.current.app=id
users.current.args=-a
users.logged.app=who
users.logged.args=-a
users.last.app=last
users.last.args=-10
disk.app=df
disk.args=-h
env.app=env
ulimit.app=bash
ulimit.args=-c\0ulimit -a
ulimit.args.delimiter=\0
system.dmesg.app=dmesg
system.sysctl.app=sysctl
system.sysctl.args=-a
process.top.app=top
process.top.args=-b -n 1
process.ps.app=ps
process.ps.args=-eo pid,pcpu,cputime,start,pmem,vsz,rssize,stackp,stat,sgi_p,wchan,user,args
memory.free.app=free
memory.free.args=-h
memory.vmstat.app=vmstat
memory.vmstat.default.args=3 3
memory.vmstat.statistics.args=-s
memory.vmstat.slabinfo.args=-m
memory.vmstat.disk.args=-d
memory.proc_meminfo.app=bash
memory.proc_meminfo.args=-c\0cat /proc/meminfo
memory.proc_meminfo.delimiter=\0
memory.proc_vmstat.app=bash
memory.proc_vmstat.args=-c\0cat /proc/vmstat
memory.proc_vmstat.delimiter=\0
memory.thp.app=bash
memory.thp.args=-c\0cat /sys/kernel/mm/transparent_hugepage/{enabled,defrag,shmem_enabled}
memory.thp.delimiter=\0
files.app=lsof
locks.app=lslocks
locks.args=-u
net.sockets.app=netstat
net.sockets.args=-aeeopv
net.statistics.app=netstat
net.statistics.args=-sv
net.ifconfig.app=ifconfig
net.ifconfig.args=-a
net.hostsfile.app=cat
net.hostsfile.args=/etc/hosts
screenshot.app=bash
screenshot.args=-c\0\
echo '\
var robot = new java.awt.Robot();\
var ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();\
var bounds = ge.getDefaultScreenDevice().getDefaultConfiguration().getBounds();\
var capture = robot.createScreenCapture(bounds);\
var file = new java.io.File("screen.png");\
javax.imageio.ImageIO.write(capture, "png", file);\
' | jshell -
screenshot.args.delimiter=\0
################################################################################

View file

@ -0,0 +1,153 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
config.execSuffix=
config.getChildren.pattern=%p
config.getChildren.app=pgrep
config.getChildren.args=-P %p
################################################################################
# process info to gather
################################################################################
onTimeout=\
native.DevToolsSecurity \
native.vmmap native.heap native.leaks native.spindump \
native.stack native.core
################################################################################
native.pattern=%p
native.javaOnly=false
native.args=%p
native.DevToolsSecurity.app=DevToolsSecurity
native.DevToolsSecurity.args=--status
# spindump requires root privileges
native.spindump.app=sudo
native.spindump.args=spindump %p -stdout
native.vmmap.app=bash
native.vmmap.delimiter=\0
native.vmmap.args=-c\0DevToolsSecurity --status | grep -q enabled && vmmap %p
native.leaks.app=bash
native.leaks.delimiter=\0
native.leaks.args=-c\0DevToolsSecurity --status | grep -q enabled && leaks %p
native.heap.app=bash
native.heap.delimiter=\0
native.heap.args=-c\0DevToolsSecurity --status | grep -q enabled && heap %p
native.stack.app=bash
native.stack.delimiter=\0
native.stack.params.repeat=6
native.stack.args=-c\0DevToolsSecurity --status | grep -q enabled && lldb -o 'attach %p' -o 'thread backtrace all' -o 'detach' -o 'quit'
# has to be the last command
native.core.app=bash
# The below trick was found on https://stackoverflow.com/a/41613532
native.core.args=-c\0kill -ABRT %p && lsof -p %p +r 1 &>/dev/null
native.core.delimiter=\0
native.core.timeout=600000
cores=native.lldb
native.lldb.app=lldb
native.lldb.delimiter=\0
# Core files can be very big and take a long time to load on macosx-aarch64.
# The 20 seconds default timeout is not nearly enough.
native.lldb.timeout=120000
# Assume that java standard laucher has been used
native.lldb.args=--core\0%p\0%java\0-o\0thread backtrace all\0-o\0quit
################################################################################
# environment info to gather
################################################################################
environment=\
users.current users.logged users.last \
disk \
env \
ulimit \
system.dmesg system.sysctl \
process.ps process.top \
memory.vmstat \
files \
net.netstat.anv net.netstat.av net.netstat.aL net.netstat.m net.netstat.s net.netstat.g net.netstat.r \
net.ifconfig net.hostsfile \
fw.up \
scutil.nwi scutil.proxy \
screenshot
################################################################################
users.current.app=id
users.current.args=-a
users.logged.app=who
users.logged.args=-a
users.last.app=last
users.last.args=-10
disk.app=df
disk.args=-h
env.app=env
ulimit.app=bash
ulimit.args=-c\0ulimit -a
ulimit.args.delimiter=\0
system.dmesg.app=sudo
system.dmesg.args=dmesg
system.sysctl.app=sysctl
system.sysctl.args=-a
process.ps.app=ps
process.ps.args=-Meo pid,pcpu,cputime,start,pmem,vsz,rss,state,wchan,user,args
process.top.app=top
process.top.args=-l 2
memory.vmstat.app=vm_stat
memory.vmstat.args=-c 3 3
files.app=lsof
net.netstat.app=netstat
net.netstat.av.args=-av
net.netstat.anv.args=-anv
net.netstat.aL.args=-aL
net.netstat.m.args=-mm
net.netstat.s.args=-s
net.netstat.g.args=-gs
net.netstat.r.args=-rn
net.ifconfig.app=ifconfig
net.ifconfig.args=-a
net.hostsfile.app=cat
net.hostsfile.args=/etc/hosts
scutil.app=scutil
scutil.nwi.args=--nwi
scutil.proxy.args=--proxy
screenshot.app=screencapture
screenshot.args=-x screen1.png screen2.png screen3.png screen4.png screen5.png
fw.app=/usr/libexec/ApplicationFirewall/socketfilterfw
fw.up.args=--getglobalstate
################################################################################

View file

@ -0,0 +1,143 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
config.execSuffix=.exe
config.getChildren.app=powershell
config.getChildren.pattern=%p
config.getChildren.args.delimiter=\0
config.getChildren.args=-NoLogo\0-Command\0"Get-CimInstance Win32_Process -Filter \\\"ParentProcessId = %p\\\" | Select-Object ProcessId" | tail -n+4
################################################################################
# process info to gather
################################################################################
onTimeout=\
native.info \
native.pmap.normal native.pmap.everything \
native.files native.locks \
native.stack native.core
################################################################################
native.pattern=%p
native.javaOnly=false
native.args=%p
native.info.app=powershell
native.info.delimiter=\0
native.info.args=-NoLogo\0-Command\0"Get-WmiObject Win32_Process -Filter \\\"ProcessId = %p\\\" | Format-List -Property *"
native.pmap.app=pmap
native.pmap.normal.args=%p
native.pmap.everything.args=-x %p
native.files.app=handle
native.files.args=-p %p
# TODO
native.locks.app=lslocks
native.locks.args=-u --pid %p
native.stack.app=cdb
native.stack.args=-c "~*kP n;qd" -p %p
native.stack.params.repeat=6
native.core.app=cdb
native.core.args=-c ".dump /mA core.%p;qd" -p %p
native.core.params.timeout=600000
cores=
################################################################################
# environment info to gather
################################################################################
environment=\
users.current users.logged \
disk \
env \
ulimit \
system.events.system system.events.application system.os \
process.top process.ps process.tasklist \
memory.free memory.vmstat.default memory.vmstat.statistics \
memory.vmstat.slabinfo memory.vmstat.disk \
files \
net.sockets net.statistics net.ipconfig net.hostsfile \
screenshot
################################################################################
users.current.app=id
users.current.args=-a
users.logged.app=query
users.logged.args=user
disk.app=df
disk.args=-h
env.app=env
ulimit.app=bash
ulimit.args=-c\0ulimit -a
ulimit.args.delimiter=\0
system.events.app=powershell
system.events.delimiter=\0
system.events.system.args=-NoLogo\0-Command\0Get-EventLog System -After (Get-Date).AddDays(-1) | Format-List
system.events.application.args=-NoLogo\0-Command\0Get-EventLog Application -After (Get-Date).AddDays(-1) | Format-List
system.os.app=powershell
system.os.delimiter=\0
system.os.args=-NoLogo\0-Command\0Get-WmiObject Win32_OperatingSystem | Format-List -Property *
process.top.app=top
process.top.args=-b -n 1
process.ps.app=ps
process.ps.args=-efW
process.tasklist.app=tasklist
process.tasklist.args=/V
memory.free.app=free
memory.vmstat.app=vmstat
memory.vmstat.statistics.args=-s
memory.vmstat.slabinfo.args=-m
memory.vmstat.disk.args=-d
files.app=openfiles
files.args=/query
net.sockets.app=bash
net.sockets.args=-c\0netstat -b -a -t -o || netstat -a -t -o
net.sockets.args.delimiter=\0
net.statistics.app=netstat
net.statistics.args=-s -e
net.ipconfig.app=ipconfig
net.ipconfig.args=/all
net.hostsfile.app=bash
net.hostsfile.args.delimiter=\0
net.hostsfile.args=-c\0cat $WINDIR/System32/drivers/etc/hosts
screenshot.app=bash
screenshot.args=-c\0\
echo '\
var robot = new java.awt.Robot();\
var ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();\
var bounds = ge.getDefaultScreenDevice().getDefaultConfiguration().getBounds();\
var capture = robot.createScreenCapture(bounds);\
var file = new java.io.File(""screen.png"");\
javax.imageio.ImageIO.write(capture, ""png"", file);\
' | jshell -
screenshot.args.delimiter=\0
################################################################################

View file

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/*
* @test
* @run main/othervm Crash
*/
public class Crash {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe u = (Unsafe) f.get(null);
u.setMemory(0, 42, (byte) 0xFF);
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary Deadlocked client
*/
public class Deadlock {
public double e;
private volatile int i;
public static void main(String[] args) {
new Deadlock().test();
}
private void test() {
final Object a = new Object();
final Object b = new Object();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (a) {
do {
i |= 1;
} while (i != 3);
synchronized (b) {
e = 1;
}
}
}}).start();
synchronized (b) {
do {
i |= 2;
} while (i != 3);
synchronized (a) {
e = 2;
}
}
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary Busy infinite loop client, calculating E number
*/
public class Livelock {
public static double elim;
public static void main(String[] args) {
System.out.printf(
"%24s %24s %24s %24s %24s %24s%n",
"n", "n!", "e = lim(...)", "e = taylor series",
"err e-lim", "err e-taylor");
while (true) {
double esum = 2;
double nfac = 1;
double iter = 1;
for (double n = 1; !Double.isInfinite(n) && !Double.isNaN(n) ; n = n * 2) {
elim = Math.pow(1 + 1 / n, n);
iter += 1;
nfac *= iter;
esum += 1 / nfac;
System.out.printf("% 24.16e % 24.16e % 24.16e % 24.16e"
+ "%- 24.16e %- 24.16e%n",
n, nfac, elim, esum, (Math.E - elim), (Math.E - esum));
}
}
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.LinkedList;
/*
* @test
* @summary Slowly eat all memory in an infinite loop
* @run main/othervm Crash
*/
public class OOME {
@SuppressWarnings ("UnusedDeclaration")
private static Object garbage;
public static void main(String args[]) {
int chunkSize = 0x8000;
LinkedList<int[]> list = new LinkedList<>();
garbage = list;
while (true) {
try {
list.add(new int[chunkSize]);
} catch (OutOfMemoryError e) {
chunkSize >>= 1;
}
}
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary Suicide test
* @run main/othervm Suicide
*/
public class Suicide {
public static void main(String[] args) {
String cmd = null;
try {
long pid = ProcessHandle.current().pid();
String osName = System.getProperty("os.name");
if (osName.contains("Windows")) {
cmd = "taskkill.exe /F /PID " + pid;
} else {
cmd = "kill -9 " + pid;
}
System.out.printf("executing `%s'%n", cmd);
Runtime.getRuntime().exec(cmd);
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
System.err.printf("TEST/ENV BUG: %s didn't kill JVM%n", cmd);
System.exit(1);
}
}

View file

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

View file

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

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.IOException;
import java.nio.file.Paths;
/*
* @test
* @build Deadlock
* @run driver WaitForDeadlock
*/
public class WaitForDeadlock {
public static void main(String[] args) throws Exception {
System.out.println("START");
ProcessBuilder pb = new ProcessBuilder(Paths.get(
System.getProperty("test.jdk"), "bin", "java").toString(),
"-cp", System.getProperty("java.class.path"),
Deadlock.class.getName());
pb.redirectError(ProcessBuilder.Redirect.to(Paths.get("out").toFile()));
pb.redirectOutput(ProcessBuilder.Redirect.to(Paths.get("err").toFile()));
int r = pb.start().waitFor();
System.out.println("END. " + r);
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import org.junit.Assert;
import org.junit.Test;
public class DefaultParserTest {
@Test
public void testParseStringArray() throws Exception {
DefaultParser parser = new DefaultParser();
String line = "a aa aaa";
String[] result = {"a", "aa", "", "", "aaa"};
Assert.assertArrayEquals(result,
(Object[]) parser.parse(result.getClass(), line, " "));
line = null;
result = new String[]{};
Assert.assertArrayEquals(result,
(Object[]) parser.parse(result.getClass(), line, " "));
}
@Test
public void testParseObjectArray() throws Exception {
DefaultParser parser = new DefaultParser();
String line = "a aa aaa";
String[] result = {"a", "aa", "", "", "aaa"};
Assert.assertArrayEquals(result,
(String[]) parser.parse(result.getClass(), line, " "));
Object[] result2 = {"a", "aa", "", "", "aaa"};
Assert.assertArrayEquals(result2,
(Object[]) parser.parse(result.getClass(), line, " "));
}
@Test
public void testParseCharArray() throws Exception {
DefaultParser parser = new DefaultParser();
String line = "a b c a";
char[] result = {'a', 'b', 'c', 'a'};
Assert.assertArrayEquals(result,
(char[]) parser.parse(result.getClass(), line, " "));
Character[] result2 = {'a', 'b', 'c', 'a'};
Assert.assertArrayEquals(result2,
(Character[]) parser.parse(result2.getClass(), line, " "));
}
@Test
public void testParseBoolean() throws Exception {
DefaultParser parser = new DefaultParser();
String line = "a b c a";
Assert.assertEquals(false,
(boolean) parser.parse(boolean.class, line, " "));
Assert.assertEquals(Boolean.FALSE,
parser.parse(Boolean.class, line, " "));
line = "trUe";
Assert.assertEquals(true,
(boolean) parser.parse(boolean.class, line, " "));
Assert.assertEquals(Boolean.TRUE,
parser.parse(Boolean.class, line, " "));
}
@Test
public void testParseShort() throws Exception {
DefaultParser parser = new DefaultParser();
Assert.assertSame("10", (short) 10,
parser.parse(short.class, "10", " "));
Assert.assertSame("010", (short) 8,
parser.parse(short.class, "010", " "));
Assert.assertSame("0x10", (short) 16,
parser.parse(short.class, "0x10", " "));
}
@Test
public void testParseByte() throws Exception {
DefaultParser parser = new DefaultParser();
Assert.assertSame("11", (byte) 11,
parser.parse(byte.class, "11", " "));
Assert.assertSame("011", (byte) 9,
parser.parse(byte.class, "011", " "));
Assert.assertSame("0x11", (byte) 17,
parser.parse(byte.class, "0x11", " "));
}
@Test
public void testParseInt() throws Exception {
DefaultParser parser = new DefaultParser();
Assert.assertEquals("20", (int) 20,
parser.parse(int.class, "20", " "));
Assert.assertEquals("020", (int) 16,
parser.parse(int.class, "020", " "));
Assert.assertEquals("0x20", (int) 32,
parser.parse(int.class, "0x20", " "));
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler.value;
import org.junit.Assert;
import org.junit.Test;
import java.lang.reflect.Field;
import java.util.Properties;
public class ValueHandlerTest {
@Test
public void testApplyAnonymousPrivateFinalInt() throws Exception {
Properties p = new Properties();
p.put("int", "010");
Object o = new Object() {
@Value (name = "int")
private final int i1 = -1;
};
Field f = o.getClass().getDeclaredField("i1");
f.setAccessible(true);
int value = f.getInt(o);
Assert.assertEquals(value, -1);
f.setAccessible(false);
ValueHandler.apply(o, p, null);
f.setAccessible(true);
value = f.getInt(o);
Assert.assertEquals(value, 8);
f.setAccessible(false);
}
@Test
public void testApplyPublicStaticWithDefault() throws Exception {
Assert.assertEquals(StaticDefaultCase.s, null);
Properties p = new Properties();
StaticDefaultCase o = new StaticDefaultCase();
ValueHandler.apply(o, p, "prefix");
Assert.assertEquals(StaticDefaultCase.s, "default");
p.put("s", "new2");
ValueHandler.apply(o, p, "prefix");
Assert.assertEquals(StaticDefaultCase.s, "new2");
p.put("prefix.s", "new");
ValueHandler.apply(o, p, "prefix");
Assert.assertEquals(StaticDefaultCase.s, "new");
ValueHandler.apply(o, p, null);
Assert.assertEquals(StaticDefaultCase.s, "new2");
}
protected class InnerClass1 {
@Value (name = "innerClass")
String[] arr = null;
}
public class InnerClass2 extends InnerClass1 {
@Value (name = "float")
float f = 0.0f;
@SubValues (prefix = "inner")
InnerClass1 inner1 = new InnerClass1();
@SubValues (prefix = "")
InnerClass1 inner2 = new InnerClass1();
}
@Test
public void testApplySub() throws Exception {
InnerClass2 o = new InnerClass2();
Assert.assertArrayEquals(o.arr, null);
Assert.assertArrayEquals(o.inner1.arr, null);
Assert.assertArrayEquals(o.inner2.arr, null);
Assert.assertEquals(o.f, 0.0f, Float.MIN_VALUE);
Properties p = new Properties();
p.put("float", "1.f");
p.put("innerClass", "a b");
p.put("inner.innerClass", "a b c");
ValueHandler.apply(o, p, "");
Assert.assertArrayEquals(o.arr, new String[]{"a", "b"});
Assert.assertArrayEquals(o.inner1.arr, new String[]{"a", "b", "c"});
Assert.assertArrayEquals(o.inner2.arr, new String[]{"a", "b"});
Assert.assertEquals(o.f, 1.0f, Float.MIN_VALUE);
}
}
class StaticDefaultCase {
@Value (name = "s")
@DefaultValue (value = "default")
public static String s;
}