/*
* Copyright (c) 2002, 2018, 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 nsk.share;
import java.io.*;
import java.lang.reflect.Method;
import java.util.*;
/**
* Class used as an agent for Java serviceability reliability testing (RAS).
* It sets different RAS options and/or modes for a special agent which
* actually performs the specified RAS testing.
* The agent recognizes arguments, started with ''-ras.
''. They
* may be as follows:
*
-ras.help
- print usage message and exit
* -ras.verbose
- verbose mode
* -ras.invoke_run
- invoke the method run(String[],PrintStream)
* of the test instead of main(String[]) which is invoked by default.
* -ras.hotswap=<stress_level>
- enable JVMTI hotswap of
* the currently running test classes. Here are the possible HotSwap stress
* levels:
*/
public class RASagent {
static final int HOTSWAP_OFF = 0;
static final int HOTSWAP_EVERY_METHOD_ENTRY = 2;
static final int HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS = 20;
static final int HOTSWAP_EVERY_SINGLE_STEP = 3;
static final int HOTSWAP_EVERY_EXCEPTION = 4;
static final int HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS = 40;
// path to the directory with class files of the invoked test
static String clfBasePath = null;
private static boolean verbose = false;
private static PrintStream out;
native static int setHotSwapMode(boolean vrb, int stress_lev,
String shortName);
public static void main(String argv[]) {
System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
}
public static int run(String argv[], PrintStream out) {
return new RASagent().runThis(argv, out);
}
private int runThis(String argv[], PrintStream out) {
int skipArgs = 1; // number of arguments which must be skipped
// for the invoked test
boolean invokeRun = false; // invoke the method "main" by default
int hotSwapMode = HOTSWAP_EVERY_METHOD_ENTRY; // HotSwap default stress level
int res;
String hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
RASagent.out = out;
if (argv.length != 0) {
// parse arguments for the RASagent and then skip them
while(argv[skipArgs-1].startsWith("-ras.")) {
if (argv[skipArgs-1].equals("-ras.verbose")) {
verbose = true;
} else if (argv[skipArgs-1].equals("-ras.help")) {
printHelp();
return Consts.TEST_FAILED;
} else if (argv[skipArgs-1].equals("-ras.invoke_run")) {
invokeRun = true;
} else if (argv[skipArgs-1].startsWith("-ras.hotswap=")) {
try {
hotSwapMode = Integer.parseInt(
argv[skipArgs-1].substring(argv[skipArgs-1].lastIndexOf("=")+1));
} catch (NumberFormatException e) {
e.printStackTrace();
out.println("\nERROR: RASagent: specified HotSwap mode \""
+ hotSwapMode + "\" is not an integer");
printHelp();
return Consts.TEST_FAILED;
}
switch(hotSwapMode) {
case HOTSWAP_EVERY_METHOD_ENTRY:
hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
break;
case HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS:
hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS";
break;
case HOTSWAP_EVERY_SINGLE_STEP:
hotSwapModeName = "HOTSWAP_EVERY_SINGLE_STEP";
break;
case HOTSWAP_EVERY_EXCEPTION:
hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION";
break;
case HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS:
hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS";
break;
default:
out.println("\nERROR: RASagent: specified HotSwap mode \""
+ hotSwapMode + "\" is unrecognized");
printHelp();
return Consts.TEST_FAILED;
}
}
skipArgs++;
}
String shortTestName = getTestNameAndPath(argv[skipArgs-1]);
display("\n#### RASagent: setting hotswap mode \""
+ hotSwapModeName + "\" for class \""
+ shortTestName + "\" ...");
if ((res = setHotSwapMode(verbose, hotSwapMode, shortTestName)) != 0) {
out.println("\nERROR: RASagent: unable to set HotSwap stress level for \""
+ shortTestName + "\", exiting");
return Consts.TEST_FAILED;
}
display("\n#### RASagent: ... setting hotswap mode done");
try {
Class testCls = Class.forName(argv[skipArgs-1]);
display("\n#### RASagent: main class \""
+ testCls.toString() + "\" loaded");
// copy arguments for the invoked test
String args[] = new String[argv.length-skipArgs];
System.arraycopy(argv, skipArgs, args, 0, args.length);
// invoke the test
if (invokeRun)
return invokeRunMethod(testCls, args);
else
return invokeMainMethod(testCls, args);
} catch(ClassNotFoundException e) {
// just pass: the invoked test is already a RAS specific one
out.println("\nWARNING: the test was not really run due to the following error:"
+ "\n\tunable to get the Class object for \""
+ argv[skipArgs-1] + "\"\n\tcaught: " + e);
return Consts.TEST_PASSED;
}
} else {
out.println("\nERROR: RASagent: required test name is absent in parameters list");
return Consts.TEST_FAILED;
}
}
/**
* Verify that test's class file exists with a path given as a parameter
* and, if so, store that path in the static field "clfBasePath".
*/
private boolean pathValid(String pathToCheck, String testName) {
String fullPath = pathToCheck + File.separator
+ testName.replace('.', File.separatorChar) + ".class";
File classFile = null;
display("\n#### RASagent: verifying class path\n