test/hotspot/jtreg/vmTestbase/nsk/share/RASagent.java
changeset 49934 44839fbb20db
equal deleted inserted replaced
49933:c63bdf53a1a7 49934:44839fbb20db
       
     1 /*
       
     2  * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package nsk.share;
       
    25 
       
    26 import java.io.*;
       
    27 import java.lang.reflect.Method;
       
    28 import java.util.*;
       
    29 
       
    30 /**
       
    31  * Class used as an agent for Java serviceability reliability testing (RAS).
       
    32  * It sets different RAS options and/or modes for a special agent which
       
    33  * actually performs the specified RAS testing.<br>
       
    34  * The agent recognizes arguments, started with ''<code>-ras.</code>''. They
       
    35  * may be as follows:<p>
       
    36  * <li><code>-ras.help</code> - print usage message and exit
       
    37  * <li><code>-ras.verbose</code> - verbose mode
       
    38  * <li><code>-ras.invoke_run</code> - invoke the method <i>run(String[],PrintStream)</i>
       
    39  * of the test instead of <i>main(String[])</i> which is invoked by default.
       
    40  * <li><code>-ras.hotswap=&lt;stress_level&gt;</code> - enable JVMTI hotswap of
       
    41  * the currently running test classes. Here are the possible HotSwap stress
       
    42  * levels:<br>
       
    43  * 0 - HotSwap off<br>
       
    44  * 2 - HotSwap tested class in every JVMTI method entry event of running test
       
    45  * (default mode)<br>
       
    46  * 20 - HotSwap tested class in every JVMTI method entry event of every class<br>
       
    47  * 3 - HotSwap tested class in every JVMTI single step event of running test<br>
       
    48  * 4 - HotSwap tested class in every JVMTI exception event of running test<br>
       
    49  * 40 - HotSwap tested class in every JVMTI exception event of every class<p>
       
    50  */
       
    51 public class RASagent {
       
    52     static final int HOTSWAP_OFF = 0;
       
    53     static final int HOTSWAP_EVERY_METHOD_ENTRY = 2;
       
    54     static final int HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS = 20;
       
    55     static final int HOTSWAP_EVERY_SINGLE_STEP = 3;
       
    56     static final int HOTSWAP_EVERY_EXCEPTION = 4;
       
    57     static final int HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS = 40;
       
    58 
       
    59     // path to the directory with class files of the invoked test
       
    60     static String clfBasePath = null;
       
    61 
       
    62     private static boolean verbose = false;
       
    63 
       
    64     private static PrintStream out;
       
    65 
       
    66     native static int setHotSwapMode(boolean vrb, int stress_lev,
       
    67         String shortName);
       
    68 
       
    69     public static void main(String argv[]) {
       
    70         System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
       
    71     }
       
    72 
       
    73     public static int run(String argv[], PrintStream out) {
       
    74         return new RASagent().runThis(argv, out);
       
    75     }
       
    76 
       
    77     private int runThis(String argv[], PrintStream out) {
       
    78         int skipArgs = 1; // number of arguments which must be skipped
       
    79                           // for the invoked test
       
    80         boolean invokeRun = false; // invoke the method "main" by default
       
    81         int hotSwapMode = HOTSWAP_EVERY_METHOD_ENTRY; // HotSwap default stress level
       
    82         int res;
       
    83         String hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
       
    84 
       
    85         RASagent.out = out;
       
    86 
       
    87         if (argv.length != 0) {
       
    88             // parse arguments for the RASagent and then skip them
       
    89             while(argv[skipArgs-1].startsWith("-ras.")) {
       
    90                 if (argv[skipArgs-1].equals("-ras.verbose")) {
       
    91                     verbose = true;
       
    92                 } else if (argv[skipArgs-1].equals("-ras.help")) {
       
    93                     printHelp();
       
    94                     return Consts.TEST_FAILED;
       
    95                 } else if (argv[skipArgs-1].equals("-ras.invoke_run")) {
       
    96                     invokeRun = true;
       
    97                 } else if (argv[skipArgs-1].startsWith("-ras.hotswap=")) {
       
    98                     try {
       
    99                         hotSwapMode = Integer.parseInt(
       
   100                            argv[skipArgs-1].substring(argv[skipArgs-1].lastIndexOf("=")+1));
       
   101                     } catch (NumberFormatException e) {
       
   102                         e.printStackTrace();
       
   103                         out.println("\nERROR: RASagent: specified HotSwap mode \""
       
   104                             + hotSwapMode + "\" is not an integer");
       
   105                         printHelp();
       
   106                         return Consts.TEST_FAILED;
       
   107                     }
       
   108                     switch(hotSwapMode) {
       
   109                         case HOTSWAP_EVERY_METHOD_ENTRY:
       
   110                             hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
       
   111                             break;
       
   112                         case HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS:
       
   113                             hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS";
       
   114                             break;
       
   115                         case HOTSWAP_EVERY_SINGLE_STEP:
       
   116                             hotSwapModeName = "HOTSWAP_EVERY_SINGLE_STEP";
       
   117                             break;
       
   118                         case HOTSWAP_EVERY_EXCEPTION:
       
   119                             hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION";
       
   120                             break;
       
   121                         case HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS:
       
   122                             hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS";
       
   123                             break;
       
   124                         default:
       
   125                             out.println("\nERROR: RASagent: specified HotSwap mode \""
       
   126                                 + hotSwapMode + "\" is unrecognized");
       
   127                             printHelp();
       
   128                             return Consts.TEST_FAILED;
       
   129                     }
       
   130                 }
       
   131                 skipArgs++;
       
   132             }
       
   133 
       
   134             String shortTestName = getTestNameAndPath(argv[skipArgs-1]);
       
   135 
       
   136             display("\n#### RASagent: setting hotswap mode \""
       
   137                 + hotSwapModeName + "\" for class \""
       
   138                 + shortTestName + "\" ...");
       
   139             if ((res = setHotSwapMode(verbose, hotSwapMode, shortTestName)) != 0) {
       
   140                 out.println("\nERROR: RASagent: unable to set HotSwap stress level for \""
       
   141                     + shortTestName + "\", exiting");
       
   142                 return Consts.TEST_FAILED;
       
   143             }
       
   144             display("\n#### RASagent: ... setting hotswap mode done");
       
   145 
       
   146             try {
       
   147                 Class testCls = Class.forName(argv[skipArgs-1]);
       
   148                 display("\n#### RASagent: main class \""
       
   149                     + testCls.toString() + "\" loaded");
       
   150 
       
   151                 // copy arguments for the invoked test
       
   152                 String args[] = new String[argv.length-skipArgs];
       
   153                 System.arraycopy(argv, skipArgs, args, 0, args.length);
       
   154 
       
   155                 // invoke the test
       
   156                 if (invokeRun)
       
   157                     return invokeRunMethod(testCls, args);
       
   158                 else
       
   159                     return invokeMainMethod(testCls, args);
       
   160             } catch(ClassNotFoundException e) {
       
   161                 // just pass: the invoked test is already a RAS specific one
       
   162                 out.println("\nWARNING: the test was not really run due to the following error:"
       
   163                     + "\n\tunable to get the Class object for \""
       
   164                     + argv[skipArgs-1] + "\"\n\tcaught: " + e);
       
   165                 return Consts.TEST_PASSED;
       
   166             }
       
   167 
       
   168         } else {
       
   169             out.println("\nERROR: RASagent: required test name is absent in parameters list");
       
   170             return Consts.TEST_FAILED;
       
   171         }
       
   172     }
       
   173 
       
   174     /**
       
   175      * Verify that test's class file exists with a path given as a parameter
       
   176      * and, if so, store that path in the static field "clfBasePath".
       
   177      */
       
   178     private boolean pathValid(String pathToCheck, String testName) {
       
   179         String fullPath = pathToCheck + File.separator
       
   180             + testName.replace('.', File.separatorChar) + ".class";
       
   181         File classFile = null;
       
   182 
       
   183         display("\n#### RASagent: verifying class path\n<RASagent>\t"
       
   184             + pathToCheck + " ...");
       
   185         try {
       
   186             classFile = new File(fullPath);
       
   187         } catch (NullPointerException e) {
       
   188             e.printStackTrace();
       
   189             out.println("\nERROR: RASagent: verification of class file "
       
   190                 + fullPath + " failed: caught " + e);
       
   191             System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
       
   192         }
       
   193 
       
   194         if (classFile.exists()) {
       
   195             clfBasePath = pathToCheck;
       
   196             display("<RASagent>\tthe class file exists:\n<RASagent>\t\t"
       
   197                 + fullPath + "\n<RASagent>\tclass file base directory found:\n"
       
   198                 + "<RASagent>\t\t" + clfBasePath
       
   199                 + "\n#### RASagent: ... class path verification done\n");
       
   200             return true;
       
   201         }
       
   202         else {
       
   203             display("<RASagent>\tno class file at location :\n\t\t"
       
   204                 + fullPath
       
   205                 + "\n#### RASagent: ... class path verification done\n");
       
   206             return false;
       
   207         }
       
   208     }
       
   209 
       
   210     /**
       
   211      * Get short name of an invoked test (i.e. without package name) and
       
   212      * store path to the directory with the test's class files.
       
   213      */
       
   214     private String getTestNameAndPath(String testName) {
       
   215         String shortTestName = testName;
       
   216         String packageName = "";
       
   217 
       
   218         // if '.' occurs, it means that current test is inside a package
       
   219         if (testName.lastIndexOf(".") != -1) {
       
   220             shortTestName = testName.substring(testName.lastIndexOf(".")+1);
       
   221             packageName = testName.substring(0, testName.lastIndexOf("."));
       
   222         }
       
   223 
       
   224         StringTokenizer clPathes = new StringTokenizer(
       
   225             System.getProperty("java.class.path"), File.pathSeparator);
       
   226 
       
   227         while(clPathes.hasMoreTokens()) {
       
   228             String clPath = clPathes.nextToken();
       
   229 
       
   230             // trying to load a class file defining the current test from
       
   231             // this entry of "java.class.path": the class file may locate
       
   232             // at the test's work directory or if it's already compiled,
       
   233             // at any directory in classpath
       
   234             if (pathValid(clPath, testName))
       
   235                 return shortTestName;
       
   236         }
       
   237 
       
   238         // directory with the test's class files was not found.
       
   239         // Actually, it means that the invoked test has own Java
       
   240         // options such as, for example, "-verify"
       
   241         out.println("\nWARNING: the test was not really run due to the following reason:"
       
   242             + "\n\tthe invoked test has the own Java option: "
       
   243             + testName);
       
   244         System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED);
       
   245 
       
   246         return null; // fake return for too smart javac
       
   247     }
       
   248 
       
   249     /**
       
   250      * Invoke the method <i>main(String[])</i> of the test.
       
   251      */
       
   252     private int invokeMainMethod(Class testCls, String args[]) {
       
   253         Class[] methType = { String[].class };
       
   254         Object[] methArgs = { args };
       
   255 
       
   256         return invokeMethod(testCls, "main", methType, methArgs);
       
   257     }
       
   258 
       
   259     /**
       
   260      * Invoke the method <i>run(String[], PrintStream)</i> of the test.
       
   261      */
       
   262     private int invokeRunMethod(Class testCls, String args[]) {
       
   263         Class[] methType = { String[].class, PrintStream.class };
       
   264         Object[] methArgs = { args, out };
       
   265 
       
   266         return invokeMethod(testCls, "run", methType, methArgs);
       
   267     }
       
   268 
       
   269     /**
       
   270      * Low level invocation of the test.
       
   271      */
       
   272     private int invokeMethod(Class<?> testCls, String methodName,
       
   273             Class methType[], Object methArgs[]) {
       
   274 
       
   275         try {
       
   276             Method testMeth = testCls.getMethod(methodName, methType);
       
   277             display("\n#### RASagent: invoking method \""
       
   278                 + testMeth.toString() + "\" ...");
       
   279 
       
   280             Object result = testMeth.invoke(null, methArgs);
       
   281 
       
   282             display("\n#### RASagent: ... invocation of \""
       
   283                 + testMeth.toString() + "\" done");
       
   284             if (result instanceof Integer) {
       
   285                 Integer retCode = (Integer) result;
       
   286                 return retCode.intValue();
       
   287             }
       
   288         } catch(NoSuchMethodException e) {
       
   289             e.printStackTrace();
       
   290             out.println("\nFAILURE: RASagent: unable to get method \""
       
   291                 + methodName + "\" in class "
       
   292                 + testCls + "\n\tcaught " + e);
       
   293             return Consts.TEST_FAILED;
       
   294         } catch(Exception e) {
       
   295             e.printStackTrace();
       
   296             out.println("\nFAILURE: RASagent: caught during invokation of the test class "
       
   297                 + testCls + " " + e);
       
   298             return Consts.TEST_FAILED;
       
   299         }
       
   300 
       
   301         return -1;
       
   302     }
       
   303 
       
   304     /**
       
   305      * Load class bytes for HotSwap.
       
   306      */
       
   307     static byte[] loadFromClassFile(String signature) {
       
   308         String testPath = clfBasePath + File.separator + signature.substring(
       
   309                 1, signature.length()-1).replace('/', File.separatorChar) + ".class";
       
   310         File classFile = null;
       
   311 
       
   312         display("\n#### RASagent: looking for class file\n<RASagent>\t"
       
   313             + testPath + " ...");
       
   314 
       
   315         try {
       
   316             classFile = new File(testPath);
       
   317         } catch (NullPointerException e) {
       
   318             out.println("\nFAILURE: RASagent: path name to the redefining class file is null");
       
   319         }
       
   320 
       
   321         display("\n#### RASagent: loading " + classFile.length()
       
   322             + " bytes from class file "+ testPath + " ...");
       
   323         byte[] buf = new byte[(int) classFile.length()];
       
   324         try {
       
   325             InputStream in = new FileInputStream(classFile);
       
   326             in.read(buf);
       
   327             in.close();
       
   328         } catch(FileNotFoundException e) {
       
   329             e.printStackTrace();
       
   330             out.println("\nFAILURE: RASagent: loadFromClassFile: file " +
       
   331                 classFile.getName() + " not found");
       
   332             System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
       
   333         } catch (Exception e) {
       
   334             e.printStackTrace();
       
   335             out.println("\nFAILURE: RASagent: unable to load bytes from the file:\n");
       
   336             out.println("\t" + testPath + ": caught " + e);
       
   337             System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
       
   338         }
       
   339 
       
   340         display("\n#### RASagent: ... " + classFile.length() + " bytes loaded");
       
   341 
       
   342         return buf;
       
   343     }
       
   344 
       
   345     /**
       
   346      * This method is used in verbose mode. It prints paramter string only
       
   347      * in case of verbose mode.
       
   348      */
       
   349     private static void display(String msg) {
       
   350         if (verbose)
       
   351             out.println(msg);
       
   352     }
       
   353 
       
   354     /**
       
   355      * This method prints out RASagent usage message.
       
   356      */
       
   357     private static void printHelp() {
       
   358         out.println("\nRASagent usage: RASagent [option, ...] test" +
       
   359             "\n\t-ras.help                 print this message and exit" +
       
   360             "\n\t-ras.verbose              verbose mode (off by default)" +
       
   361             "\n\t-ras.hotswap=mode         enable HotSwap of the running test classes" +
       
   362             "\n\t\twhere mode is:" +
       
   363             "\n\t\t\t" + HOTSWAP_EVERY_METHOD_ENTRY
       
   364                 + " - hotswap tested class in its every method entry event" +
       
   365             "\n\t\t\t" + HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS
       
   366                 + " - hotswap tested class in every method entry event for every class" +
       
   367             "\n\t\t\t" + HOTSWAP_EVERY_SINGLE_STEP
       
   368                 + " - hotswap tested class in its every single step event" +
       
   369             "\n\t\t\t" + HOTSWAP_EVERY_EXCEPTION
       
   370                 + " - hotswap tested class in its every exception event" +
       
   371             "\n\t\t\t" + HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS
       
   372                 + " - hotswap tested class in every exception event for every class\n" +
       
   373             "\n\t-ras.invoke_run           invoke the method run() of the test" +
       
   374             "\n\t\tinstead of main() by default");
       
   375     }
       
   376 }