Home | History | Annotate | Download | only in share
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *
     15  *  See the License for the specific language governing permissions and
     16  *  limitations under the License.
     17  */
     18 
     19 /**
     20  * @author Vitaly A. Provodin
     21  */
     22 
     23 /**
     24  * Created on 29.01.2005
     25  */
     26 package org.apache.harmony.jpda.tests.jdwp.share;
     27 
     28 import org.apache.harmony.jpda.tests.framework.TestErrorException;
     29 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
     30 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
     31 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
     32 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
     33 import org.apache.harmony.jpda.tests.framework.jdwp.Packet;
     34 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
     35 
     36 /**
     37  * Basic class for unit tests which use only one debuggee VM.
     38  */
     39 public abstract class JDWPTestCase extends JDWPRawTestCase {
     40 
     41     /**
     42      * DebuggeeWrapper instance for launched debuggee VM.
     43      */
     44     protected JDWPUnitDebuggeeWrapper debuggeeWrapper;
     45 
     46     /**
     47      * EventPacket instance with received VM_START event.
     48      */
     49     protected EventPacket initialEvent = null;
     50 
     51     /**
     52      * Overrides inherited method to launch one debuggee VM, establish JDWP
     53      * connection, and wait for VM_START event.
     54      */
     55     protected void internalSetUp() throws Exception {
     56         super.internalSetUp();
     57 
     58         // launch debuggee process
     59         debuggeeWrapper = createDebuggeeWrapper();
     60         beforeConnectionSetUp();
     61         setUpDebuggeeWrapperConnection();
     62         beforeDebuggeeStart();
     63         startDebuggeeWrapper();
     64 
     65         // receive and handle initial event
     66         receiveInitialEvent();
     67 
     68         // adjust JDWP types length
     69         debuggeeWrapper.vmMirror.adjustTypeLength();
     70         logWriter.println("Adjusted VM-dependent type lengths");
     71     }
     72 
     73     /**
     74      * Creates wrapper for debuggee process.
     75      */
     76     protected JDWPUnitDebuggeeWrapper createDebuggeeWrapper() {
     77         if (settings.getDebuggeeLaunchKind().equals("manual")) {
     78             return new JDWPManualDebuggeeWrapper(settings, logWriter);
     79         } else {
     80             return new JDWPUnitDebuggeeWrapper(settings, logWriter);
     81         }
     82     }
     83 
     84     /**
     85      * Set up server side JDWP connection.
     86      */
     87     protected void setUpDebuggeeWrapperConnection() {
     88         debuggeeWrapper.setUpConnection();
     89         logWriter.println("Set up server side JDWP connection.");
     90     }
     91 
     92     /**
     93      * Starts wrapper for debuggee process.
     94      */
     95     protected void startDebuggeeWrapper() {
     96         debuggeeWrapper.start();
     97         logWriter.println("Established JDWP connection with debuggee VM");
     98     }
     99 
    100     /**
    101      * Receives initial VM_INIT event if debuggee is suspended on event.
    102      */
    103     protected void receiveInitialEvent() {
    104         if (settings.isDebuggeeSuspend()) {
    105             initialEvent =
    106                 debuggeeWrapper.vmMirror.receiveCertainEvent(JDWPConstants.EventKind.VM_INIT);
    107             logWriter.println("Received inital VM_INIT event");
    108         }
    109     }
    110 
    111     /**
    112      * Overrides inherited method to stop started debuggee VM and close all
    113      * connections.
    114      */
    115     protected void internalTearDown() {
    116         if (debuggeeWrapper != null) {
    117             debuggeeWrapper.stop();
    118             logWriter.println("Closed JDWP connection with debuggee VM");
    119         }
    120         super.internalTearDown();
    121     }
    122 
    123     /**
    124      * This method is invoked right before setting up the server side JDWP connection.
    125      */
    126     protected void beforeConnectionSetUp() {
    127       // Empty.
    128     }
    129 
    130     /**
    131      * This method is invoked right before starting debuggee VM.
    132      */
    133     protected void beforeDebuggeeStart() {
    134       // Empty.
    135     }
    136 
    137     /**
    138      * Opens JDWP connection with debuggee (doesn't run debuggee and doesn't
    139      * establish synchronize connection).
    140      */
    141     public void openConnection() {
    142         debuggeeWrapper.openConnection();
    143         logWriter.println("Opened transport connection");
    144         debuggeeWrapper.vmMirror.adjustTypeLength();
    145         logWriter.println("Adjusted VM-dependent type lengths");
    146     }
    147 
    148     /**
    149      * Closes JDWP connection with debuggee (doesn't terminate debuggee and
    150      * doesn't stop synchronize connection).
    151      */
    152     public void closeConnection() {
    153         if (debuggeeWrapper != null) {
    154             debuggeeWrapper.disposeConnection();
    155             try {
    156                 debuggeeWrapper.vmMirror.closeConnection();
    157             } catch (Exception e) {
    158                 throw new TestErrorException(e);
    159             }
    160             logWriter.println("Closed transport connection");
    161         }
    162     }
    163 
    164     /**
    165      * Helper that returns reference type signature of input object ID.
    166      *
    167      * @param objectID -
    168      *            debuggee object ID
    169      * @return object signature of reference type
    170      */
    171     protected String getObjectSignature(long objectID) {
    172         long classID = getObjectReferenceType(objectID);
    173         return getClassSignature(classID);
    174     }
    175 
    176     /**
    177      * Helper that returns reference type ID for input object ID.
    178      *
    179      * @param objectID -
    180      *            debuggee object ID
    181      * @return reference type ID
    182      */
    183     protected long getObjectReferenceType(long objectID) {
    184         CommandPacket command = new CommandPacket(
    185                 JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
    186                 JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand);
    187         command.setNextValueAsReferenceTypeID(objectID);
    188         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
    189         checkReplyPacket(reply, "ObjectReference::ReferenceType command");
    190         // byte refTypeTag =
    191         reply.getNextValueAsByte();
    192         long objectRefTypeID = reply.getNextValueAsReferenceTypeID();
    193         return objectRefTypeID;
    194     }
    195 
    196     /**
    197      * Helper for getting method ID of corresponding class and method name.
    198      *
    199      * @param classID -
    200      *            class ID
    201      * @param methodName -
    202      *            method name
    203      * @return method ID
    204      */
    205     protected long getMethodID(long classID, String methodName) {
    206         CommandPacket command = new CommandPacket(
    207                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    208                 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
    209         command.setNextValueAsClassID(classID);
    210         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
    211         checkReplyPacket(reply, "ReferenceType::Methods command");
    212         int methods = reply.getNextValueAsInt();
    213         for (int i = 0; i < methods; i++) {
    214             long methodID = reply.getNextValueAsMethodID();
    215             String name = reply.getNextValueAsString(); // method name
    216             reply.getNextValueAsString(); // method signature
    217             reply.getNextValueAsInt(); // method modifiers
    218             if (name.equals(methodName)) {
    219                 return methodID;
    220             }
    221         }
    222         return -1;
    223     }
    224 
    225     /**
    226      * Helper for getting method ID of corresponding class, method name and signature.
    227      *
    228      * @param classID -
    229      *            class ID
    230      * @param methodName -
    231      *            method name
    232      * @param methodSignature -
    233      *            method signature
    234      * @return method ID
    235      */
    236     protected long getMethodID(long classID, String methodName, String methodSignature) {
    237         CommandPacket command = new CommandPacket(
    238                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    239                 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
    240         command.setNextValueAsClassID(classID);
    241         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
    242         checkReplyPacket(reply, "ReferenceType::Methods command");
    243         int methods = reply.getNextValueAsInt();
    244         for (int i = 0; i < methods; i++) {
    245             long methodID = reply.getNextValueAsMethodID();
    246             String name = reply.getNextValueAsString(); // method name
    247             String signature = reply.getNextValueAsString();
    248             reply.getNextValueAsInt(); // method modifiers
    249             if (name.equals(methodName) && signature.equals(methodSignature)) {
    250                 return methodID;
    251             }
    252         }
    253         return -1;
    254     }
    255 
    256     /**
    257      * Issues LineTable command.
    258      *
    259      * @param classID -
    260      *            class ID
    261      * @param methodID -
    262      *            method ID
    263      * @return reply packet
    264      */
    265     protected ReplyPacket getLineTable(long classID, long methodID) {
    266         CommandPacket lineTableCommand = new CommandPacket(
    267                 JDWPCommands.MethodCommandSet.CommandSetID,
    268                 JDWPCommands.MethodCommandSet.LineTableCommand);
    269         lineTableCommand.setNextValueAsReferenceTypeID(classID);
    270         lineTableCommand.setNextValueAsMethodID(methodID);
    271         ReplyPacket lineTableReply = debuggeeWrapper.vmMirror
    272                 .performCommand(lineTableCommand);
    273         checkReplyPacket(lineTableReply, "Method::LineTable command");
    274         return lineTableReply;
    275     }
    276 
    277     /**
    278      * Helper for getting method name of corresponding class and method ID.
    279      *
    280      * @param classID class id
    281      * @param methodID method id
    282      * @return String
    283      */
    284     protected String getMethodName(long classID, long methodID) {
    285         CommandPacket packet = new CommandPacket(
    286                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    287                 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
    288         packet.setNextValueAsClassID(classID);
    289         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    290         checkReplyPacket(reply, "ReferenceType::Methods command");
    291         int methods = reply.getNextValueAsInt();
    292         for (int i = 0; i < methods; i++) {
    293             long mid = reply.getNextValueAsMethodID();
    294             String name = reply.getNextValueAsString();
    295             reply.getNextValueAsString();
    296             reply.getNextValueAsInt();
    297             if (mid == methodID) {
    298                 return name;
    299             }
    300         }
    301         return "unknown";
    302     }
    303 
    304     /**
    305      * Returns jni signature for selected classID
    306      *
    307      * @param classID
    308      * @return jni signature for selected classID
    309      */
    310     protected String getClassSignature(long classID) {
    311         CommandPacket command = new CommandPacket(
    312                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    313                 JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
    314         command.setNextValueAsReferenceTypeID(classID);
    315         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(command);
    316         checkReplyPacket(reply, "ReferenceType::Signature command");
    317         String signature = reply.getNextValueAsString();
    318         return signature;
    319     }
    320 
    321     /**
    322      * Returns classID for the selected jni signature
    323      *
    324      * @param signature
    325      * @return classID for the selected jni signature
    326      */
    327     protected long getClassIDBySignature(String signature) {
    328         logWriter.println("=> Getting reference type ID for class: "
    329                 + signature);
    330         CommandPacket packet = new CommandPacket(
    331                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
    332                 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
    333         packet.setNextValueAsString(signature);
    334         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    335         checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command");
    336         int classes = reply.getNextValueAsInt();
    337         logWriter.println("=> Returned number of classes: " + classes);
    338         long classID = 0;
    339         for (int i = 0; i < classes; i++) {
    340             reply.getNextValueAsByte();
    341             classID = reply.getNextValueAsReferenceTypeID();
    342             reply.getNextValueAsInt();
    343             // we need the only class, even if there were multiply ones
    344             break;
    345         }
    346         assertTrue(
    347                 "VirtualMachine::ClassesBySignature command returned invalid classID:<"
    348                         + classID + "> for signature " + signature, classID > 0);
    349         return classID;
    350     }
    351 
    352     /**
    353      * Returns reference type ID.
    354      *
    355      * @param signature
    356      * @return type ID for the selected jni signature
    357      */
    358     protected long getReferenceTypeID(String signature) {
    359         CommandPacket packet = new CommandPacket(
    360                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
    361                 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
    362         packet.setNextValueAsString(signature);
    363         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    364         checkReplyPacket(reply, "VirtualMachine::ClassesBySignature command");
    365         int classes = reply.getNextValueAsInt();
    366         // this class may be loaded only once
    367         assertEquals("Invalid number of classes for reference type: "
    368                 + signature + ",", 1, classes);
    369         byte refTypeTag = reply.getNextValueAsByte();
    370         long classID = reply.getNextValueAsReferenceTypeID();
    371         int status = reply.getNextValueAsInt();
    372         logWriter.println("VirtualMachine.ClassesBySignature: classes="
    373                 + classes + " refTypeTag=" + refTypeTag + " typeID= " + classID
    374                 + " status=" + status);
    375         assertAllDataRead(reply);
    376         assertEquals("", JDWPConstants.TypeTag.CLASS, refTypeTag);
    377         return classID;
    378     }
    379 
    380     /**
    381      * Helper function for resuming debuggee.
    382      */
    383     protected void resumeDebuggee() {
    384         logWriter.println("=> Resume debuggee");
    385         CommandPacket packet = new CommandPacket(
    386                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
    387                 JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
    388         logWriter.println("Sending VirtualMachine::Resume command...");
    389         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    390         checkReplyPacket(reply, "VirtualMachine::Resume command");
    391         assertAllDataRead(reply);
    392     }
    393 
    394     /**
    395      * Performs string creation in debuggee.
    396      *
    397      * @param value -
    398      *            content for new string
    399      * @return StringID of new created string
    400      */
    401     protected long createString(String value) {
    402         CommandPacket packet = new CommandPacket(
    403                 JDWPCommands.VirtualMachineCommandSet.CommandSetID,
    404                 JDWPCommands.VirtualMachineCommandSet.CreateStringCommand);
    405         packet.setNextValueAsString(value);
    406         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    407         checkReplyPacket(reply, "VirtualMachine::CreateString command");
    408         long stringID = reply.getNextValueAsStringID();
    409         return stringID;
    410     }
    411 
    412     /**
    413      * Returns corresponding string from string ID.
    414      *
    415      * @param stringID -
    416      *            string ID
    417      * @return string value
    418      */
    419     protected String getStringValue(long stringID) {
    420         CommandPacket packet = new CommandPacket(
    421                 JDWPCommands.StringReferenceCommandSet.CommandSetID,
    422                 JDWPCommands.StringReferenceCommandSet.ValueCommand);
    423         packet.setNextValueAsObjectID(stringID);
    424         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    425         checkReplyPacket(reply, "StringReference::Value command");
    426         String returnedTestString = reply.getNextValueAsString();
    427         return returnedTestString;
    428     }
    429 
    430     /**
    431      * Multiple field verification routine.
    432      *
    433      * @param refTypeID -
    434      *            reference type ID
    435      * @param checkedFieldNames -
    436      *            list of field names to be checked
    437      * @return list of field IDs
    438      */
    439     protected long[] checkFields(long refTypeID, String checkedFieldNames[]) {
    440         return checkFields(refTypeID, checkedFieldNames, null, null);
    441     }
    442 
    443     /**
    444      * Single field verification routine.
    445      *
    446      * @param refTypeID -
    447      *            reference type ID
    448      * @param fieldName -
    449      *            name of single field
    450      * @return filed ID
    451      */
    452     protected long checkField(long refTypeID, String fieldName) {
    453         return checkFields(refTypeID, new String[] { fieldName }, null, null)[0];
    454     }
    455 
    456     /**
    457      * Multiple field verification routine.
    458      *
    459      * @param refTypeID -
    460      *            reference type ID
    461      * @param checkedFieldNames -
    462      *            list of field names to be checked
    463      * @param expectedSignatures -
    464      *            list of expected field signatures
    465      * @param expectedModifiers -
    466      *            list of expected field modifiers
    467      * @return list of field IDs
    468      */
    469     protected long[] checkFields(long refTypeID, String checkedFieldNames[],
    470             String expectedSignatures[], int expectedModifiers[]) {
    471 
    472         boolean checkedFieldFound[] = new boolean[checkedFieldNames.length];
    473         long checkedFieldIDs[] = new long[checkedFieldNames.length];
    474 
    475         logWriter
    476                 .println("=> Send ReferenceType::Fields command and get field ID(s)");
    477 
    478         CommandPacket fieldsCommand = new CommandPacket(
    479                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    480                 JDWPCommands.ReferenceTypeCommandSet.FieldsCommand);
    481         fieldsCommand.setNextValueAsReferenceTypeID(refTypeID);
    482         ReplyPacket fieldsReply = debuggeeWrapper.vmMirror
    483                 .performCommand(fieldsCommand);
    484         fieldsCommand = null;
    485         checkReplyPacket(fieldsReply, "ReferenceType::Fields command");
    486 
    487         int returnedFieldsNumber = fieldsReply.getNextValueAsInt();
    488         logWriter
    489                 .println("=> Returned fields number = " + returnedFieldsNumber);
    490 
    491         int checkedFieldsNumber = checkedFieldNames.length;
    492         final int fieldSyntheticFlag = 0xf0000000;
    493 
    494         int nameDuplicated = 0;
    495         String fieldNameDuplicated = null; // <= collects all duplicated fields
    496         int nameMissing = 0;
    497         String fieldNameMissing = null; // <= collects all missed fields
    498 
    499         for (int i = 0; i < returnedFieldsNumber; i++) {
    500             long returnedFieldID = fieldsReply.getNextValueAsFieldID();
    501             String returnedFieldName = fieldsReply.getNextValueAsString();
    502             String returnedFieldSignature = fieldsReply.getNextValueAsString();
    503             int returnedFieldModifiers = fieldsReply.getNextValueAsInt();
    504             logWriter.println("");
    505             logWriter.println("=> Field ID: " + returnedFieldID);
    506             logWriter.println("=> Field name: " + returnedFieldName);
    507             logWriter.println("=> Field signature: " + returnedFieldSignature);
    508             logWriter.println("=> Field modifiers: 0x"
    509                     + Integer.toHexString(returnedFieldModifiers));
    510             if ((returnedFieldModifiers & fieldSyntheticFlag) == fieldSyntheticFlag) {
    511                 continue; // do not check synthetic fields
    512             }
    513             for (int k = 0; k < checkedFieldsNumber; k++) {
    514                 if (!checkedFieldNames[k].equals(returnedFieldName)) {
    515                     continue;
    516                 }
    517                 if (checkedFieldFound[k]) {
    518                     logWriter.println("");
    519                     logWriter
    520                             .println("## FAILURE: The field is found repeatedly in the list");
    521                     logWriter.println("## Field Name: " + returnedFieldName);
    522                     logWriter.println("## Field ID: " + returnedFieldID);
    523                     logWriter.println("## Field Signature: "
    524                             + returnedFieldSignature);
    525                     logWriter.println("## Field Modifiers: 0x"
    526                             + Integer.toHexString(returnedFieldModifiers));
    527                     fieldNameDuplicated = (0 == nameDuplicated ? returnedFieldName
    528                             : fieldNameDuplicated + "," + returnedFieldName);
    529                     nameDuplicated++;
    530                     break;
    531                 }
    532                 checkedFieldFound[k] = true;
    533                 checkedFieldIDs[k] = returnedFieldID;
    534                 if (null != expectedSignatures) {
    535                     assertString(
    536                             "Invalid field signature is returned for field:"
    537                                     + returnedFieldName + ",",
    538                             expectedSignatures[k], returnedFieldSignature);
    539                 }
    540                 if (null != expectedModifiers) {
    541                     assertEquals(
    542                             "Invalid field modifiers are returned for field:"
    543                                     + returnedFieldName + ",",
    544                             expectedModifiers[k], returnedFieldModifiers);
    545                 }
    546                 break;
    547             }
    548         }
    549 
    550         for (int k = 0; k < checkedFieldsNumber; k++) {
    551             if (!checkedFieldFound[k]) {
    552                 logWriter.println("");
    553                 logWriter
    554                         .println("\n## FAILURE: Expected field is NOT found in the list of retuned fields:");
    555                 logWriter.println("## Field name = " + checkedFieldNames[k]);
    556                 fieldNameMissing = 0 == nameMissing ? checkedFieldNames[k]
    557                         : fieldNameMissing + "," + checkedFieldNames[k];
    558                 nameMissing++;
    559                 // break;
    560             }
    561         }
    562 
    563         // String thisTestName = this.getClass().getName();
    564         // logWriter.println("==> " + thisTestName + " for " + thisCommandName +
    565         // ": FAILED");
    566 
    567         if (nameDuplicated > 1) {
    568             fail("Duplicated fields are found in the retuned by FieldsCommand list: "
    569                     + fieldNameDuplicated);
    570         }
    571         if (nameDuplicated > 0) {
    572             fail("Duplicated field is found in the retuned by FieldsCommand list: "
    573                     + fieldNameDuplicated);
    574         }
    575         if (nameMissing > 1) {
    576             fail("Expected fields are NOT found in the retuned by FieldsCommand list: "
    577                     + fieldNameMissing);
    578         }
    579         if (nameMissing > 0) {
    580             fail("Expected field is NOT found in the retuned by FieldsCommand list: "
    581                     + fieldNameMissing);
    582         }
    583 
    584         logWriter.println("");
    585         if (1 == checkedFieldsNumber) {
    586             logWriter
    587                     .println("=> Expected field was found and field ID was got");
    588         } else {
    589             logWriter
    590                     .println("=> Expected fields were found and field IDs were got");
    591         }
    592 
    593         assertAllDataRead(fieldsReply);
    594         return checkedFieldIDs;
    595     }
    596 
    597     /**
    598      * Checks thread status and suspend status of a thread
    599      *
    600      * @param eventThreadID
    601      *          the thread ID to check
    602      * @param expectedThreadStatus
    603      *          the expected thread status
    604      * @param expectedSuspendStatus
    605      *          the expected suspend status
    606      */
    607     protected void checkThreadState(long eventThreadID, byte expectedThreadStatus,
    608             byte expectedSuspendStatus) {
    609         CommandPacket commandPacket = new CommandPacket(
    610                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
    611                 JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
    612         commandPacket.setNextValueAsThreadID(eventThreadID);
    613         ReplyPacket replyPacket = debuggeeWrapper.vmMirror.performCommand(commandPacket);
    614         debuggeeWrapper.vmMirror.checkReply(replyPacket);
    615 
    616         int threadStatus = replyPacket.getNextValueAsInt();
    617         int suspendStatus = replyPacket.getNextValueAsInt();
    618         assertAllDataRead(replyPacket);
    619 
    620         assertEquals("Invalid thread status", threadStatus, expectedThreadStatus,
    621                 JDWPConstants.ThreadStatus.getName(expectedThreadStatus),
    622                 JDWPConstants.ThreadStatus.getName(threadStatus));
    623         assertEquals("Invalid suspend status", suspendStatus, expectedSuspendStatus,
    624                 JDWPConstants.SuspendStatus.getName(expectedSuspendStatus),
    625                 JDWPConstants.SuspendStatus.getName(suspendStatus));
    626     }
    627 
    628     /**
    629      * Helper for checking reply packet error code. Calls junit fail if packet
    630      * error code does not equal to expected error code.
    631      *
    632      * @param reply -
    633      *            returned from debuggee packet
    634      * @param message -
    635      *            additional message
    636      * @param errorCodeExpected -
    637      *            array of expected error codes
    638      */
    639     protected void checkReplyPacket(ReplyPacket reply, String message,
    640             int errorCodeExpected) {
    641         checkReplyPacket(reply, message, new int[] { errorCodeExpected });
    642     }
    643 
    644     /**
    645      * Helper for checking reply packet error code. Calls junit fail if packet
    646      * error code does not equal NONE.
    647      *
    648      * @param reply -
    649      *            returned from debuggee packet
    650      * @param message -
    651      *            additional message
    652      */
    653     protected void checkReplyPacket(ReplyPacket reply, String message) {
    654         checkReplyPacket(reply, message, JDWPConstants.Error.NONE);
    655     }
    656 
    657     /**
    658      * Helper for checking reply packet error code. Calls junit fail if packet
    659      * error code does not equal to expected error code.
    660      *
    661      * @param reply -
    662      *            returned from debuggee packet
    663      * @param message -
    664      *            additional message
    665      * @param expected -
    666      *            array of expected error codes
    667      */
    668     protected void checkReplyPacket(ReplyPacket reply, String message,
    669             int[] expected) {
    670         checkReplyPacket(reply, message, expected, true /* failSign */);
    671     }
    672 
    673     /**
    674      * Helper for checking reply packet error code. If reply packet does not
    675      * have error - returns true. Otherwise does not call junit fail - simply
    676      * prints error message and returns false. if packet error code does not
    677      * equal NONE.
    678      *
    679      * @param reply -
    680      *            returned from debuggee packet
    681      * @param message -
    682      *            additional message
    683      * @return true if error is not found, or false otherwise
    684      */
    685     protected boolean checkReplyPacketWithoutFail(ReplyPacket reply,
    686             String message) {
    687         return checkReplyPacket(reply, message,
    688                 new int[] { JDWPConstants.Error.NONE }, false /* failSign */);
    689     }
    690 
    691     /**
    692      * Helper for checking reply packet error code. If reply packet does not
    693      * have unexpected error - returns true. If reply packet has got unexpected
    694      * error: If failSign param = true - calls junit fail. Otherwise prints
    695      * message about error and returns false.
    696      *
    697      * @param reply -
    698      *            returned from debuggee packet
    699      * @param message -
    700      *            additional message
    701      * @param expected -
    702      *            array of expected error codes
    703      * @param failSign -
    704      *            defines to call junit fail or not
    705      * @return true if unexpected errors are not found, or false otherwise
    706      */
    707     protected boolean checkReplyPacket(ReplyPacket reply, String message,
    708             int[] expected, boolean failSign) {
    709         // check reply code against expected
    710         int errorCode = reply.getErrorCode();
    711         for (int i = 0; i < expected.length; i++) {
    712             if (reply.getErrorCode() == expected[i]) {
    713                 return true; // OK
    714             }
    715         }
    716 
    717         // replay code validation failed
    718         // start error message composition
    719         if (null == message) {
    720             message = "";
    721         } else {
    722             message = message + ", ";
    723         }
    724 
    725         // format error message
    726         if (expected.length == 1 && JDWPConstants.Error.NONE == expected[0]) {
    727             message = message + "Error Code:<" + errorCode + "("
    728                     + JDWPConstants.Error.getName(errorCode) + ")>";
    729         } else {
    730             message = message + "Unexpected error code:<" + errorCode + "("
    731                     + JDWPConstants.Error.getName(errorCode) + ")>"
    732                     + ", Expected error code"
    733                     + (expected.length == 1 ? ":" : "s:");
    734             for (int i = 0; i < expected.length; i++) {
    735                 message = message + (i > 0 ? ",<" : "<") + expected[i] + "("
    736                         + JDWPConstants.Error.getName(expected[i]) + ")>";
    737             }
    738         }
    739 
    740         if (failSign) {
    741             printErrorAndFail(message);
    742         }
    743         logWriter.printError(message);
    744         return false;
    745     }
    746 
    747     /**
    748      * Helper for comparison numbers and printing string equivalents.
    749      *
    750      * @param message -
    751      *            user message
    752      * @param expected -
    753      *            expected value
    754      * @param actual -
    755      *            actual value
    756      * @param strExpected -
    757      *            string equivalent of expected value
    758      * @param strActual -
    759      *            string equivalent of actual value
    760      */
    761     protected void assertEquals(String message, long expected, long actual,
    762             String strExpected, String strActual) {
    763         if (expected == actual) {
    764             return; // OK
    765         }
    766 
    767         if (null == message) {
    768             message = "";
    769         }
    770 
    771         if (null == strExpected) {
    772             strExpected = expected + "";
    773         } else {
    774             strExpected = expected + "(" + strExpected + ")";
    775         }
    776 
    777         if (null == strActual) {
    778             strActual = actual + "";
    779         } else {
    780             strActual = actual + "(" + strActual + ")";
    781         }
    782 
    783         printErrorAndFail(message + " expected:<" + strExpected + "> but was:<"
    784                 + strActual + ">");
    785     }
    786 
    787     /**
    788      * Asserts that two strings are equal.
    789      *
    790      * @param message -
    791      *            user message
    792      * @param expected -
    793      *            expected string
    794      * @param actual -
    795      *            actual string
    796      */
    797     protected void assertString(String message, String expected, String actual) {
    798         if (null == expected) {
    799             expected = "";
    800         }
    801         if (null == actual) {
    802             actual = "";
    803         }
    804         if (expected.equals(actual)) {
    805             return; // OK
    806         }
    807         printErrorAndFail(message + " expected:<" + expected + "> but was:<"
    808                 + actual + ">");
    809     }
    810 
    811     /**
    812      * Helper for checking reply packet data has been read.
    813      *
    814      * @param reply -
    815      *            reply packet from debuggee
    816      */
    817     protected void assertAllDataRead(Packet reply) {
    818         if (reply.isAllDataRead()) {
    819             return; // OK
    820         }
    821         printErrorAndFail("Not all data has been read");
    822     }
    823 
    824     /**
    825      * Asserts that two JDWP event kinds are equal.
    826      *
    827      * @param message
    828      *          user message
    829      * @param expected
    830      *          expected event kind
    831      * @param actual
    832      *          actual event kind
    833      */
    834     protected void assertEventKindEquals(String message, byte expected, byte actual) {
    835         if (expected != actual) {
    836             StringBuilder builder = new StringBuilder(message);
    837             builder.append(": expected ");
    838             builder.append(expected);
    839             builder.append(" (");
    840             builder.append(JDWPConstants.EventKind.getName(expected));
    841             builder.append(") but was ");
    842             builder.append(actual);
    843             builder.append(" (");
    844             builder.append(JDWPConstants.EventKind.getName(actual));
    845             builder.append(")");
    846             printErrorAndFail(builder.toString());
    847         }
    848     }
    849 
    850     /**
    851      * Asserts that two JDWP tags are equal.
    852      *
    853      * @param message
    854      *          user message
    855      * @param expected
    856      *          expected tag
    857      * @param actual
    858      *          actual tag
    859      */
    860     protected void assertTagEquals(String message, byte expected, byte actual) {
    861         if (expected != actual) {
    862             StringBuilder builder = new StringBuilder(message);
    863             builder.append(": expected ");
    864             builder.append(expected);
    865             builder.append(" (");
    866             builder.append(JDWPConstants.Tag.getName(expected));
    867             builder.append(") but was ");
    868             builder.append(actual);
    869             builder.append(" (");
    870             builder.append(JDWPConstants.Tag.getName(actual));
    871             builder.append(")");
    872             printErrorAndFail(builder.toString());
    873         }
    874     }
    875 
    876     /**
    877      * Prints error message in log writer and in junit fail.
    878      *
    879      * @param message -
    880      *            error message
    881      */
    882     protected void printErrorAndFail(String message) {
    883         logWriter.printError(message);
    884         fail(message);
    885     }
    886 
    887     /**
    888      * Helper for setting static int field in class with new value.
    889      *
    890      * @param classSignature -
    891      *            String defining signature of class
    892      * @param fieldName -
    893      *            String defining field name in specified class
    894      * @param newValue -
    895      *            int value to set for specified field
    896      * @return true, if setting is successfully, or false otherwise
    897      */
    898     protected boolean setStaticIntField(String classSignature,
    899             String fieldName, int newValue) {
    900 
    901         long classID = debuggeeWrapper.vmMirror.getClassID(classSignature);
    902         if (classID == -1) {
    903             logWriter
    904                     .println("## setStaticIntField(): Can NOT get classID for class signature = '"
    905                             + classSignature + "'");
    906             return false;
    907         }
    908 
    909         long fieldID = debuggeeWrapper.vmMirror.getFieldID(classID, fieldName);
    910         if (fieldID == -1) {
    911             logWriter
    912                     .println("## setStaticIntField(): Can NOT get fieldID for field = '"
    913                             + fieldName + "'");
    914             return false;
    915         }
    916 
    917         CommandPacket packet = new CommandPacket(
    918                 JDWPCommands.ClassTypeCommandSet.CommandSetID,
    919                 JDWPCommands.ClassTypeCommandSet.SetValuesCommand);
    920         packet.setNextValueAsReferenceTypeID(classID);
    921         packet.setNextValueAsInt(1);
    922         packet.setNextValueAsFieldID(fieldID);
    923         packet.setNextValueAsInt(newValue);
    924 
    925         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    926         int errorCode = reply.getErrorCode();
    927         if (errorCode != JDWPConstants.Error.NONE) {
    928             logWriter
    929                     .println("## setStaticIntField(): Can NOT set value for field = '"
    930                             + fieldName
    931                             + "' in class = '"
    932                             + classSignature
    933                             + "'; ClassType.SetValues command reurns error = "
    934                             + errorCode);
    935             return false;
    936         }
    937         return true;
    938     }
    939 
    940     /**
    941      * Removes breakpoint of the given event kind corresponding to the given
    942      * request id.
    943      *
    944      * @param eventKind
    945      *            request event kind
    946      * @param requestID
    947      *            request id
    948      * @param verbose
    949      *            print or don't extra log info
    950      */
    951     protected void clearEvent(byte eventKind, int requestID, boolean verbose) {
    952         CommandPacket packet = new CommandPacket(
    953                 JDWPCommands.EventRequestCommandSet.CommandSetID,
    954                 JDWPCommands.EventRequestCommandSet.ClearCommand);
    955         packet.setNextValueAsByte(eventKind);
    956         packet.setNextValueAsInt(requestID);
    957         if (verbose) {
    958             logWriter.println("Clearing event: "
    959                     + JDWPConstants.EventKind.getName(eventKind) + ", id: "
    960                     + requestID);
    961         }
    962         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
    963         checkReplyPacket(reply, "EventRequest::Clear command");
    964         assertAllDataRead(reply);
    965     }
    966 }
    967