test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java
changeset 50317 cf71bff5f533
equal deleted inserted replaced
50316:60ebcc705421 50317:cf71bff5f533
       
     1 /*
       
     2  * Copyright (c) 2001, 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.jdwp.VirtualMachine.RedefineClasses;
       
    25 
       
    26 import java.io.*;
       
    27 
       
    28 import nsk.share.*;
       
    29 import nsk.share.jpda.*;
       
    30 import nsk.share.jdwp.*;
       
    31 
       
    32 /**
       
    33  * Test for JDWP command: VirtualMachine.RedefineClasses.
       
    34  *
       
    35  * See redefinecls001.README for description of test execution.
       
    36  *
       
    37  * This class represents debugger part of the test.
       
    38  * Test is executed by invoking method runIt().
       
    39  * JDWP command is tested in the method testCommand().
       
    40  *
       
    41  * @see #runIt()
       
    42  * @see #testCommand()
       
    43  */
       
    44 public class redefinecls001 {
       
    45 
       
    46     // exit status constants
       
    47     static final int JCK_STATUS_BASE = 95;
       
    48     static final int PASSED = 0;
       
    49     static final int FAILED = 2;
       
    50 
       
    51     // VM capability constatnts
       
    52     static final int VM_CAPABILITY_NUMBER = JDWP.Capability.CAN_REDEFINE_CLASSES;
       
    53     static final String VM_CAPABILITY_NAME = "canRedefineClasses";
       
    54 
       
    55     // package and classes names
       
    56     static final String PACKAGE_NAME = "nsk.jdwp.VirtualMachine.RedefineClasses";
       
    57     static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "redefinecls001";
       
    58     static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a";
       
    59 
       
    60     // tested JDWP command
       
    61     static final String JDWP_COMMAND_NAME = "VirtualMachine.RedefineClasses";
       
    62     static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.RedefineClasses;
       
    63 
       
    64     // tested class name and signature
       
    65     static final String TESTED_CLASS_NAME = TEST_CLASS_NAME + "b";
       
    66     static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";";
       
    67 
       
    68     // field and method names
       
    69     static final String CONSTRUCTOR_FIELD_NAME = "constructorInvoked";
       
    70     static final String STATIC_METHOD_FIELD_NAME = "staticMethodInvoked";
       
    71     static final String OBJECT_METHOD_FIELD_NAME = "objectMethodInvoked";
       
    72     static final String BREAKPOINT_METHOD_NAME = "runIt";
       
    73     static final int BREAKPOINT_LINE_BEFORE = redefinecls001a.BREAKPOINT_LINE_BEFORE;
       
    74     static final int BREAKPOINT_LINE_AFTER = redefinecls001a.BREAKPOINT_LINE_AFTER;
       
    75 
       
    76     // filename for redefined class
       
    77 //   4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS
       
    78 //   precomiled class was removed
       
    79 //    static final String REDEFINED_CLASS_FILE_NAME = "redefinecls001b.klass";
       
    80     static final String REDEFINED_CLASS_FILE_NAME = "newclass"
       
    81                     + File.separator + PACKAGE_NAME.replace('.',File.separatorChar)
       
    82                     + File.separator + "redefinecls001b.class";
       
    83 //    static final String REDEFINED_CLASS_DIR = ".";
       
    84 
       
    85     // usual scaffold objects
       
    86     ArgumentHandler argumentHandler = null;
       
    87     Log log = null;
       
    88     Binder binder = null;
       
    89     Debugee debugee = null;
       
    90     Transport transport = null;
       
    91     int waitTime = 0;  // minutes
       
    92     long timeout = 0;  // milliseconds
       
    93     String testDir = null;
       
    94     boolean dead = false;
       
    95     boolean success = true;
       
    96 
       
    97     // data obtained from debuggee
       
    98     long debugeeClassID = 0;
       
    99     long testedClassID = 0;
       
   100     long breakpointMethodID = 0;
       
   101     ByteBuffer redefinedClassBytes = null;
       
   102 
       
   103     // -------------------------------------------------------------------
       
   104 
       
   105     /**
       
   106      * Start test from command line.
       
   107      */
       
   108     public static void main (String argv[]) {
       
   109         System.exit(run(argv,System.out) + JCK_STATUS_BASE);
       
   110     }
       
   111 
       
   112     /**
       
   113      * Start JCK-compilant test.
       
   114      */
       
   115     public static int run(String argv[], PrintStream out) {
       
   116         return new redefinecls001().runIt(argv, out);
       
   117     }
       
   118 
       
   119     // -------------------------------------------------------------------
       
   120 
       
   121     /**
       
   122      * Perform test execution.
       
   123      */
       
   124     public int runIt(String argv[], PrintStream out) {
       
   125 
       
   126         // make log for debugger messages
       
   127         argumentHandler = new ArgumentHandler(argv);
       
   128         log = new Log(out, argumentHandler);
       
   129         waitTime = argumentHandler.getWaitTime();  // minutes
       
   130         timeout = waitTime * 60 * 1000;           // milliseconds
       
   131 
       
   132         // get testDir as first positional parameter
       
   133         String args[] = argumentHandler.getArguments();
       
   134         if (args.length < 1) {
       
   135             log.complain("Test dir required as the first positional argument");
       
   136             return FAILED;
       
   137         }
       
   138         testDir = args[0];
       
   139 
       
   140         // execute test and display results
       
   141         try {
       
   142             log.display("\n>>> Loading redefined class \n");
       
   143 
       
   144             // load class file for redefined class
       
   145             log.display("Loading bytecode of redefined class from file: " +
       
   146                         REDEFINED_CLASS_FILE_NAME);
       
   147             redefinedClassBytes = loadClassBytes(REDEFINED_CLASS_FILE_NAME, testDir);
       
   148             log.display("   ... loaded bytes: " + redefinedClassBytes.length());
       
   149 
       
   150             log.display("\n>>> Starting debugee \n");
       
   151 
       
   152             // launch debuggee
       
   153             binder = new Binder(argumentHandler, log);
       
   154             log.display("Launching debugee VM");
       
   155             debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME);
       
   156             transport = debugee.getTransport();
       
   157             log.display("  ... debuggee launched");
       
   158 
       
   159             // set timeout for debuggee responces
       
   160             log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)");
       
   161             transport.setReadTimeout(timeout);
       
   162             log.display("  ... timeout set");
       
   163 
       
   164             // wait for VM_INIT event
       
   165             log.display("Waiting for VM_INIT event");
       
   166             debugee.waitForVMInit();
       
   167             log.display("  ... VM_INIT event received");
       
   168 
       
   169             // query debugee for VM-dependent ID sizes
       
   170             log.display("Querying for IDSizes");
       
   171             debugee.queryForIDSizes();
       
   172             log.display("  ... size of VM-dependent types adjusted");
       
   173 
       
   174             // check for VM capability
       
   175             log.display("\n>>> Checking VM capability \n");
       
   176             log.display("Getting new VM capability: " + VM_CAPABILITY_NAME);
       
   177             boolean capable = debugee.getNewCapability(VM_CAPABILITY_NUMBER, VM_CAPABILITY_NAME);
       
   178             log.display("  ... got VM capability: " + capable);
       
   179 
       
   180             // exit as PASSED if this capability is not supported
       
   181             if (!capable) {
       
   182                 out.println("TEST PASSED: unsupported VM capability: "
       
   183                             + VM_CAPABILITY_NAME);
       
   184                 return PASSED;
       
   185             }
       
   186 
       
   187             // prepare debuggee for testing and obtain required data
       
   188             log.display("\n>>> Getting prepared for testing \n");
       
   189             prepareForTest();
       
   190 
       
   191             // test JDWP command
       
   192             log.display("\n>> Testing JDWP command \n");
       
   193             testCommand();
       
   194 
       
   195             // check command results
       
   196             if (success) {
       
   197                 log.display("\n>>> Checking result of tested command \n");
       
   198                 checkResult();
       
   199             }
       
   200 
       
   201             // finish debuggee
       
   202             log.display("\n>> Finishing debuggee \n");
       
   203 
       
   204             // resume debuggee after testing command
       
   205             log.display("Resuming debuggee");
       
   206             debugee.resume();
       
   207             log.display("  ... debuggee resumed");
       
   208 
       
   209             // wait for VM_DEATH event
       
   210             log.display("Waiting for VM_DEATH event");
       
   211             debugee.waitForVMDeath();
       
   212             log.display("  ... VM_DEATH event received");
       
   213             dead = true;
       
   214 
       
   215         } catch (Failure e) {
       
   216             log.complain("TEST FAILED: " + e.getMessage());
       
   217             success = false;
       
   218         } catch (Exception e) {
       
   219             e.printStackTrace(out);
       
   220             log.complain("Caught unexpected exception while running the test:\n\t" + e);
       
   221             success = false;
       
   222         } finally {
       
   223             log.display("\n>>> Finishing test \n");
       
   224 
       
   225             // disconnect debugee and wait for its exit
       
   226             if (debugee != null) {
       
   227                 quitDebugee();
       
   228             }
       
   229         }
       
   230 
       
   231         // check result
       
   232         if (!success) {
       
   233             log.complain("TEST FAILED");
       
   234             return FAILED;
       
   235         }
       
   236         out.println("TEST PASSED");
       
   237         return PASSED;
       
   238     }
       
   239 
       
   240     /**
       
   241      * Get debuggee prepared for testing and obtain required data.
       
   242      */
       
   243     void prepareForTest() {
       
   244         // wait for debuggee and tested classes loaded on debuggee startup
       
   245         log.display("Waiting for classes loaded:"
       
   246                         + "\n\t" + DEBUGEE_CLASS_NAME
       
   247                         + "\n\t" + TESTED_CLASS_NAME);
       
   248         String classNames[] = {DEBUGEE_CLASS_NAME, TESTED_CLASS_NAME};
       
   249         long classIDs[] = debugee.waitForClassesLoaded(classNames,
       
   250                                                     JDWP.SuspendPolicy.ALL);
       
   251         debugeeClassID = classIDs[0];
       
   252         log.display("  ... debuggee class loaded with classID: " + debugeeClassID);
       
   253         testedClassID = classIDs[1];
       
   254         log.display("  ... tested class loaded with classID: " + testedClassID);
       
   255         log.display("");
       
   256 
       
   257         // set breakpoint before redefinition and wait for debugee reached it
       
   258         log.display("Waiting for breakpoint before redefiniton reached at: "
       
   259                     + BREAKPOINT_METHOD_NAME + ":" +  BREAKPOINT_LINE_BEFORE);
       
   260         long threadID = debugee.waitForBreakpointReached(debugeeClassID,
       
   261                                                 BREAKPOINT_METHOD_NAME,
       
   262                                                 BREAKPOINT_LINE_BEFORE,
       
   263                                                 JDWP.SuspendPolicy.ALL);
       
   264         log.display("  ... breakpoint before redefinition reached with threadID: " + threadID);
       
   265         log.display("");
       
   266     }
       
   267 
       
   268     /**
       
   269      * Perform testing JDWP command.
       
   270      */
       
   271     void testCommand() {
       
   272         int length = redefinedClassBytes.length();
       
   273         // create command packet and fill requred out data
       
   274         log.display("Create command packet:");
       
   275         log.display("Command: " + JDWP_COMMAND_NAME);
       
   276         CommandPacket command = new CommandPacket(JDWP_COMMAND_ID);
       
   277         log.display("  classes: " + 1);
       
   278         command.addInt(1);
       
   279         log.display("  refTypeID: " + testedClassID);
       
   280         command.addReferenceTypeID(testedClassID);
       
   281         log.display("  classfile: " + length + " bytes");
       
   282         command.addInt(length);
       
   283         log.display("  classbytes:\n" + redefinedClassBytes);
       
   284         command.addBytes(redefinedClassBytes.getBytes(), 0, length);
       
   285         command.setLength();
       
   286 
       
   287         // send command packet to debugee
       
   288         try {
       
   289             log.display("Sending command packet:\n" + command);
       
   290             transport.write(command);
       
   291         } catch (IOException e) {
       
   292             log.complain("Unable to send command packet:\n\t" + e);
       
   293             success = false;
       
   294             return;
       
   295         }
       
   296 
       
   297         // receive reply packet from debugee
       
   298         ReplyPacket reply = new ReplyPacket();
       
   299         try {
       
   300             log.display("Waiting for reply packet");
       
   301             transport.read(reply);
       
   302             log.display("  ... reply packet received:\n" + reply);
       
   303         } catch (IOException e) {
       
   304             log.complain("Unable to read reply packet for tested command:\n\t" + e);
       
   305             success = false;
       
   306             return;
       
   307         }
       
   308 
       
   309         // check reply packet header
       
   310         try{
       
   311             log.display("Checking header of reply packet");
       
   312             reply.checkHeader(command.getPacketID());
       
   313             log.display("  ... packet header is correct");
       
   314         } catch (BoundException e) {
       
   315             log.complain("Wrong header of reply packet for tested command:\n\t"
       
   316                         + e.getMessage());
       
   317             success = false;
       
   318             return;
       
   319         }
       
   320 
       
   321         // start parsing reply packet data
       
   322         log.display("Parsing reply packet data:");
       
   323         reply.resetPosition();
       
   324 
       
   325         // no reply data to parse
       
   326         log.display("  no reply data");
       
   327 
       
   328         // check for extra data in reply packet
       
   329         if (!reply.isParsed()) {
       
   330             log.complain("Extra trailing bytes found in reply packet at: "
       
   331                         + reply.offsetString());
       
   332             success = false;
       
   333         }
       
   334 
       
   335         log.display("  ... packed data parsed");
       
   336     }
       
   337 
       
   338     /**
       
   339      * Check result of the tested JDWP command.
       
   340      */
       
   341     void checkResult() {
       
   342         // set breakpoint after redefinition and wait for debugee reached it
       
   343         log.display("Waiting for breakpoint after redefiniton reached at: "
       
   344                     + BREAKPOINT_METHOD_NAME + ":" +  BREAKPOINT_LINE_AFTER);
       
   345         long threadID = debugee.waitForBreakpointReached(debugeeClassID,
       
   346                                                 BREAKPOINT_METHOD_NAME,
       
   347                                                 BREAKPOINT_LINE_AFTER,
       
   348                                                 JDWP.SuspendPolicy.ALL);
       
   349         log.display("  ... breakpoint after redefinition reached with threadID: " + threadID);
       
   350         log.display("");
       
   351 
       
   352         // check invoked methods
       
   353         log.display("Getting value of static field: " + CONSTRUCTOR_FIELD_NAME);
       
   354         JDWP.Value value = debugee.getStaticFieldValue(testedClassID,
       
   355                                                 CONSTRUCTOR_FIELD_NAME, JDWP.Tag.INT);
       
   356         int constructorInvoked = ((Integer)value.getValue()).intValue();
       
   357         log.display("  ... got constructorInvoked:  " + methodKind(constructorInvoked));
       
   358 
       
   359         if (constructorInvoked != redefinecls001b.NOT_REDEFINED_METHOD_INVOKED) {
       
   360             log.complain("Constructor has been invoked after class redefinition");
       
   361             success = false;
       
   362         }
       
   363 
       
   364         log.display("Getting value of static field: " + STATIC_METHOD_FIELD_NAME);
       
   365         value = debugee.getStaticFieldValue(testedClassID,
       
   366                                                 STATIC_METHOD_FIELD_NAME, JDWP.Tag.INT);
       
   367         int staticMethodInvoked = ((Integer)value.getValue()).intValue();
       
   368         log.display("  ... got staticMethodInvoked: " + methodKind(staticMethodInvoked));
       
   369 
       
   370         if (staticMethodInvoked != redefinecls001b.REDEFINED_METHOD_INVOKED) {
       
   371             log.complain("Not redefined static method is invoked after class redefinition");
       
   372             success = false;
       
   373         }
       
   374 
       
   375         log.display("Getting value of static field: " + OBJECT_METHOD_FIELD_NAME);
       
   376         value = debugee.getStaticFieldValue(testedClassID,
       
   377                                                 OBJECT_METHOD_FIELD_NAME, JDWP.Tag.INT);
       
   378         int objectMethodInvoked = ((Integer)value.getValue()).intValue();
       
   379         log.display("  ... got objectMethodInvoked: " + methodKind(objectMethodInvoked));
       
   380 
       
   381         if (objectMethodInvoked != redefinecls001b.REDEFINED_METHOD_INVOKED) {
       
   382             log.complain("Not redefined object method is invoked after class redefinition");
       
   383             success = false;
       
   384         }
       
   385     }
       
   386 
       
   387     /**
       
   388      * Load class bytes form the given file.
       
   389      */
       
   390     ByteBuffer loadClassBytes(String fileName, String dirName) {
       
   391         String fileSep = System.getProperty("file.separator");
       
   392         String filePath = dirName + fileSep + fileName;
       
   393 
       
   394         String error = "Unable to read bytes from class file:\n\t" + filePath;
       
   395 
       
   396         int length = 0;
       
   397         byte bytes[] = null;
       
   398         try {
       
   399             File file = new File(filePath);
       
   400             length = (int)file.length();
       
   401             FileInputStream is = new FileInputStream(file);
       
   402             bytes = new byte[length];
       
   403             int number = is.read(bytes);
       
   404             if (number < 0) {
       
   405                 log.complain("EOF reached while reading bytes from file");
       
   406                 throw new Failure(error);
       
   407             } else if (number != length) {
       
   408                 log.complain("Unexpected number of bytes red from file: " + number
       
   409                             + " (expected: " + length + ")");
       
   410                 throw new Failure(error);
       
   411             }
       
   412             is.close();
       
   413         } catch ( IOException e ) {
       
   414             log.complain("Caught IOException while reading bytes from file:\n\t" + e);
       
   415             throw new Failure(error);
       
   416         }
       
   417         ByteBuffer byteBuffer = new ByteBuffer(length, 0);
       
   418         byteBuffer.addBytes(bytes, 0, length);
       
   419         return byteBuffer;
       
   420     }
       
   421 
       
   422     /**
       
   423      * Disconnect debuggee and wait for it exited.
       
   424      */
       
   425     void quitDebugee() {
       
   426         if (debugee == null)
       
   427             return;
       
   428 
       
   429         // disconnect debugee
       
   430         if (!dead) {
       
   431             try {
       
   432                 log.display("Disconnecting debuggee");
       
   433                 debugee.dispose();
       
   434                 log.display("  ... debuggee disconnected");
       
   435             } catch (Failure e) {
       
   436                 log.display("Failed to finally disconnect debuggee:\n\t"
       
   437                             + e.getMessage());
       
   438             }
       
   439         }
       
   440 
       
   441         // wait for debugee exited
       
   442         log.display("Waiting for debuggee exit");
       
   443         int code = debugee.waitFor();
       
   444         log.display("  ... debuggee exited with exit code: " + code);
       
   445 
       
   446         // analize debugee exit status code
       
   447         if (code != JCK_STATUS_BASE + PASSED) {
       
   448             log.complain("Debuggee FAILED with exit code: " + code);
       
   449             success = false;
       
   450         }
       
   451     }
       
   452 
       
   453     // return string representation of kind of invoked method
       
   454     private static String methodKind(int kind) {
       
   455         switch (kind) {
       
   456             case redefinecls001b.METHOD_NOT_INVOKED:
       
   457                 return "METHOD_NOT_INVOKED";
       
   458             case redefinecls001b.REDEFINED_METHOD_INVOKED:
       
   459                 return "REDEFINED_METHOD_INVOKED";
       
   460             case redefinecls001b.NOT_REDEFINED_METHOD_INVOKED:
       
   461                 return "NOT_REDEFINED_METHOD_INVOKED";
       
   462             default:
       
   463                 return "UNKNOWN_METHOD_KIND";
       
   464         }
       
   465     }
       
   466 }