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