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