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 */ getFieldValue(String classSignature, String fieldName)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 */ createBreakpointEventBuilder(byte typeTag, Breakpoint breakpoint)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 */ createExceptionEventBuilder( String exceptionClassSignature, boolean caught, boolean uncaught)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 */ createMethodEntryEventBuilder(String className)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 */ createMethodExitEventBuilder(String className)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 */ createMethodExitWithReturnValueEventBuilder(String className)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 */ createThreadStartBuilder()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 */ createThreadEndBuilder()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 */ createFieldAccessEventBuilder(byte typeTag, String classSignature, String fieldName)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 */ createFieldModificationEventBuilder(byte typeTag, String classSignature, String fieldName)176 protected EventBuilder createFieldModificationEventBuilder(byte typeTag, 177 String classSignature, String fieldName) { 178 return createFieldEventBuilder(typeTag, classSignature, fieldName, true); 179 } 180 createFieldEventBuilder(byte typeTag, String typeSignature, String fieldName, boolean modification)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 */ requestEvent(Event event)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 */ waitForEvent(byte eventKind, int requestID)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 */ clearAndResume(byte eventKind, int requestID)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 */ canWatchFieldAccessCapability()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 */ canWatchFieldModificationCapability()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 */ logCapabilityWarning(String capabilityName)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