Home | History | Annotate | Download | only in EventModifiers
      1 package org.apache.harmony.jpda.tests.jdwp.EventModifiers;
      2 
      3 import org.apache.harmony.jpda.tests.framework.Breakpoint;
      4 import org.apache.harmony.jpda.tests.framework.jdwp.Event;
      5 import org.apache.harmony.jpda.tests.framework.jdwp.EventBuilder;
      6 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
      7 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
      8 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
      9 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
     10 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.EventThread;
     11 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
     12 import org.apache.harmony.jpda.tests.framework.jdwp.Value;
     13 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
     14 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
     15 
     16 /**
     17  * This base class provides utilities for all event modifier tests.
     18  */
     19 abstract class JDWPEventModifierTestCase extends JDWPSyncTestCase {
     20     /**
     21      * The suspend policy used for all events in the tests.
     22      */
     23     protected static final byte
     24             TEST_SUSPEND_POLICY = JDWPConstants.SuspendPolicy.ALL;
     25 
     26     /**
     27      * Returns value of the requested field.
     28      *
     29      * @param classSignature the signature of the field's declaring class
     30      * @param fieldName the field name.
     31      * @return the value of the field
     32      */
     33     protected Value getFieldValue(String classSignature, String fieldName) {
     34         long classID = debuggeeWrapper.vmMirror.getClassID(classSignature);
     35         assertTrue("Failed to find debuggee class " + classSignature,
     36                 classID != 0);
     37         long fieldID = debuggeeWrapper.vmMirror.getFieldID(classID, fieldName);
     38         assertTrue("Failed to find field " + classSignature + "." + fieldName,
     39                 fieldID != 0);
     40 
     41         long[] fieldIDs = new long[] { fieldID };
     42         Value[] fieldValues = debuggeeWrapper.vmMirror.getReferenceTypeValues(
     43                 classID, fieldIDs);
     44         assertNotNull("Failed to get field values for class " + classSignature,
     45                 fieldValues);
     46         assertEquals("Invalid number of field values", 1, fieldValues.length);
     47         return fieldValues[0];
     48     }
     49 
     50     /**
     51      * Creates an {@link EventBuilder} for BREAKPOINT event and sets a
     52      * LocationOnly modifier.
     53      *
     54      * @param typeTag the type tag of the location's class
     55      * @param breakpoint the breakpoint info
     56      * @return a new {@link EventBuilder}
     57      */
     58     protected EventBuilder createBreakpointEventBuilder(byte typeTag,
     59             Breakpoint breakpoint) {
     60         long typeID = debuggeeWrapper.vmMirror.getTypeID(breakpoint.className, typeTag);
     61         long methodID = getMethodID(typeID, breakpoint.methodName);
     62         byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
     63         EventBuilder builder = new EventBuilder(eventKind, TEST_SUSPEND_POLICY);
     64         builder.setLocationOnly(new Location(typeTag, typeID, methodID,
     65                 breakpoint.index));
     66         return builder;
     67     }
     68 
     69     /**
     70      * Creates an {@link EventBuilder} for EXCEPTION event and sets an
     71      * ExceptionOnly modifier.
     72      *
     73      * @param exceptionClassSignature the signature of the exception class
     74      * @param caught whether the exception must be caught
     75      * @param uncaught whether the exception must be uncaught
     76      * @return a new {@link EventBuilder}
     77      */
     78     protected EventBuilder createExceptionEventBuilder(
     79             String exceptionClassSignature, boolean caught, boolean uncaught) {
     80         byte eventKind = JDWPConstants.EventKind.EXCEPTION;
     81         EventBuilder builder = new EventBuilder(eventKind, TEST_SUSPEND_POLICY);
     82         long exceptionClassID = debuggeeWrapper.vmMirror.getClassID(
     83                 exceptionClassSignature);
     84         assertTrue("Failed to find type ID " + exceptionClassSignature,
     85                 exceptionClassID != 1);
     86         builder.setExceptionOnly(exceptionClassID, caught, uncaught);
     87         return builder;
     88     }
     89 
     90     /**
     91      * Creates an {@link EventBuilder} for METHOD_ENTRY event and sets a
     92      * ClassMatch modifier.
     93      *
     94      * @param className a regular expression of class names matching the method
     95      * entry events.
     96      * @return a new {@link EventBuilder}
     97      */
     98     protected EventBuilder createMethodEntryEventBuilder(String className) {
     99         EventBuilder builder = new EventBuilder(
    100                 JDWPConstants.EventKind.METHOD_ENTRY, TEST_SUSPEND_POLICY);
    101         return builder.setClassMatch(className);
    102     }
    103 
    104     /**
    105      * Creates an {@link EventBuilder} for METHOD_EXIT event and sets a
    106      * ClassMatch modifier.
    107      *
    108      * @param className a regular expression of class names matching the method
    109      * exit events.
    110      * @return a new {@link EventBuilder}
    111      */
    112     protected EventBuilder createMethodExitEventBuilder(String className) {
    113         EventBuilder builder = new EventBuilder(
    114                 JDWPConstants.EventKind.METHOD_EXIT, TEST_SUSPEND_POLICY);
    115         return builder.setClassMatch(className);
    116     }
    117 
    118     /**
    119      * Creates an {@link EventBuilder} for METHOD_EXIT_WITH_RETURN_VALUE event
    120      * and sets a ClassMatch modifier.
    121      *
    122      * @param className a regular expression of class names matching the method
    123      * exit events.
    124      * @return a new {@link EventBuilder}
    125      */
    126     protected EventBuilder createMethodExitWithReturnValueEventBuilder(String className) {
    127         EventBuilder builder = new EventBuilder(
    128                 JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE,
    129                 TEST_SUSPEND_POLICY);
    130         return builder.setClassMatch(className);
    131     }
    132 
    133     /**
    134      * Creates an {@link EventBuilder} for THREAD_START event.
    135      *
    136      * @return a new {@link EventBuilder}
    137      */
    138     protected EventBuilder createThreadStartBuilder() {
    139         return new EventBuilder(JDWPConstants.EventKind.THREAD_START,
    140                 TEST_SUSPEND_POLICY);
    141     }
    142 
    143     /**
    144      * Creates an {@link EventBuilder} for THREAD_END event.
    145      *
    146      * @return a new {@link EventBuilder}
    147      */
    148     protected EventBuilder createThreadEndBuilder() {
    149         return new EventBuilder(JDWPConstants.EventKind.THREAD_END,
    150                 TEST_SUSPEND_POLICY);
    151     }
    152 
    153     /**
    154      * Creates an {@link EventBuilder} for FIELD_ACCESS event and sets a
    155      * FieldOnly modifier.
    156      *
    157      * @param typeTag the type tag of the field's declaring class
    158      * @param classSignature the field's declaring class signature
    159      * @param fieldName the field name
    160      * @return a new {@link EventBuilder}
    161      */
    162     protected EventBuilder createFieldAccessEventBuilder(byte typeTag,
    163             String classSignature, String fieldName) {
    164         return createFieldEventBuilder(typeTag, classSignature, fieldName, false);
    165     }
    166 
    167     /**
    168      * Creates an {@link EventBuilder} for FIELD_MODIFICATION event and sets a
    169      * FieldOnly modifier.
    170      *
    171      * @param typeTag the type tag of the field's declaring class
    172      * @param classSignature the field's declaring class signature
    173      * @param fieldName the field name
    174      * @return a new {@link EventBuilder}
    175      */
    176     protected EventBuilder createFieldModificationEventBuilder(byte typeTag,
    177             String classSignature, String fieldName) {
    178         return createFieldEventBuilder(typeTag, classSignature, fieldName, true);
    179     }
    180 
    181     private EventBuilder createFieldEventBuilder(byte typeTag,
    182                                                 String typeSignature,
    183                                                 String fieldName,
    184                                                 boolean modification) {
    185         byte eventKind;
    186         if (modification) {
    187             eventKind = JDWPConstants.EventKind.FIELD_MODIFICATION;
    188         } else {
    189             eventKind = JDWPConstants.EventKind.FIELD_ACCESS;
    190         }
    191         EventBuilder builder = new EventBuilder(eventKind, TEST_SUSPEND_POLICY);
    192         long typeID = debuggeeWrapper.vmMirror.getTypeID(typeSignature, typeTag);
    193         assertTrue("Failed to find type ID " + typeSignature, typeID != 1);
    194         long fieldID = debuggeeWrapper.vmMirror.getFieldID(typeID, fieldName);
    195         assertTrue("Failed to find field ID " + typeSignature + "." + fieldName,
    196                 fieldID != 1);
    197         builder.setFieldOnly(typeID, fieldID);
    198         return builder;
    199     }
    200 
    201     /**
    202      * Sends a request for the given event.
    203      *
    204      * @param event the event to request
    205      * @return the request ID
    206      */
    207     protected int requestEvent(Event event) {
    208         String eventName = JDWPConstants.EventKind.getName(event.eventKind);
    209         logWriter.println("Requesting " + eventName);
    210         ReplyPacket reply = debuggeeWrapper.vmMirror.setEvent(event);
    211         checkReplyPacket(reply, "Failed to request " + eventName);
    212         int requestID = reply.getNextValueAsInt();
    213         assertAllDataRead(reply);
    214         return requestID;
    215     }
    216 
    217     /**
    218      * Waits for the first corresponding event.
    219      *
    220      * @param eventKind the event kind
    221      * @param requestID the event request ID
    222      * @return the event
    223      */
    224     protected EventThread waitForEvent(byte eventKind, int requestID) {
    225         logWriter.println("Signaling debuggee to continue");
    226         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
    227 
    228         String eventName = JDWPConstants.EventKind.getName(eventKind);
    229         logWriter.println(
    230                 "Waiting for " + eventName + " with requestID " + requestID + " ...");
    231         EventPacket eventPacket = debuggeeWrapper.vmMirror.receiveCertainEvent(
    232                 eventKind);
    233         ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket);
    234         assertNotNull(parsedEvents);
    235         assertTrue(parsedEvents.length > 0);
    236         ParsedEvent event = parsedEvents[0];
    237         assertEquals(eventKind, event.getEventKind());
    238         assertEquals(requestID, event.getRequestID());
    239         logWriter.println("Received " + eventName + " event");
    240         return (EventThread) event;
    241     }
    242 
    243     /**
    244      * Clears the corresponding event and resumes the VM.
    245      *
    246      * @param eventKind the event kind
    247      * @param requestID the event request ID
    248      */
    249     protected void clearAndResume(byte eventKind, int requestID) {
    250         clearEvent(eventKind, requestID, true);
    251         resumeDebuggee();
    252     }
    253 
    254     /**
    255      * Checks the VM supports the canWatchFieldAccess capability. If it does
    256      * not, prints a warning in the console.
    257      *
    258      * @return true if the VM supports the canWatchFieldAccess capability, false
    259      * otherwise.
    260      */
    261     protected boolean canWatchFieldAccessCapability() {
    262         logWriter.println("Checking canWatchFieldAccess capability");
    263         boolean result = debuggeeWrapper.vmMirror.canWatchFieldAccess();
    264         if (!result) {
    265             logCapabilityWarning("canWatchFieldAccess");
    266         }
    267         return result;
    268     }
    269 
    270     /**
    271      * Checks the VM supports the canWatchFieldModification capability. If it
    272      * does not, prints a warning in the console.
    273      *
    274      * @return true if the VM supports the canWatchFieldModification capability,
    275      * false otherwise.
    276      */
    277     protected boolean canWatchFieldModificationCapability() {
    278         logWriter.println("Checking canWatchFieldModification capability");
    279         boolean result = debuggeeWrapper.vmMirror.canWatchFieldModification();
    280         if (!result) {
    281             logCapabilityWarning("canWatchFieldModification");
    282         }
    283         return result;
    284     }
    285 
    286     /**
    287      * Warns about an unsupported capability by printing a message in the
    288      * console.
    289      *
    290      * @param capabilityName the capability name
    291      */
    292     protected void logCapabilityWarning(String capabilityName) {
    293         // Build the message to prompt.
    294         StringBuilder messageBuilder =
    295                 new StringBuilder("# WARNING: this VM doesn't possess capability: ");
    296         messageBuilder.append(capabilityName);
    297         messageBuilder.append(' ');
    298         messageBuilder.append('#');
    299         String message = messageBuilder.toString();
    300 
    301         // Build a sharp string long enough.
    302         int sharpLineLength = message.length();
    303         StringBuilder sharpLineBuilder = new StringBuilder(sharpLineLength);
    304         for (int i = 0; i < sharpLineLength; ++i) {
    305             sharpLineBuilder.append('#');
    306         }
    307         String sharpLine = sharpLineBuilder.toString();
    308 
    309         // Print warning message.
    310         logWriter.println(sharpLine);
    311         logWriter.println(message);
    312         logWriter.println(sharpLine);
    313     }
    314 }
    315