1package org.apache.harmony.jpda.tests.jdwp.EventModifiers; 2 3import org.apache.harmony.jpda.tests.framework.Breakpoint; 4import org.apache.harmony.jpda.tests.framework.jdwp.Event; 5import org.apache.harmony.jpda.tests.framework.jdwp.EventBuilder; 6import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket; 7import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 8import org.apache.harmony.jpda.tests.framework.jdwp.Location; 9import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent; 10import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.EventThread; 11import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 12import org.apache.harmony.jpda.tests.framework.jdwp.Value; 13import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase; 14import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 15 16/** 17 * This base class provides utilities for all event modifier tests. 18 */ 19abstract 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 return Event.builder(eventKind, TEST_SUSPEND_POLICY) 64 .setLocationOnly(new Location(typeTag, typeID, methodID, breakpoint.index)); 65 } 66 67 /** 68 * Creates an {@link EventBuilder} for EXCEPTION event and sets an 69 * ExceptionOnly modifier. 70 * 71 * @param exceptionClassSignature the signature of the exception class 72 * @param caught whether the exception must be caught 73 * @param uncaught whether the exception must be uncaught 74 * @return a new {@link EventBuilder} 75 */ 76 protected EventBuilder createExceptionEventBuilder( 77 String exceptionClassSignature, boolean caught, boolean uncaught) { 78 byte eventKind = JDWPConstants.EventKind.EXCEPTION; 79 long exceptionClassID = debuggeeWrapper.vmMirror.getClassID( 80 exceptionClassSignature); 81 assertTrue("Failed to find type ID " + exceptionClassSignature, 82 exceptionClassID != 1); 83 return Event.builder(eventKind, TEST_SUSPEND_POLICY).setExceptionOnly(exceptionClassID, 84 caught, uncaught); 85 } 86 87 /** 88 * Creates an {@link EventBuilder} for METHOD_ENTRY event and sets a 89 * ClassMatch modifier. 90 * 91 * @param className a regular expression of class names matching the method 92 * entry events. 93 * @return a new {@link EventBuilder} 94 */ 95 protected EventBuilder createMethodEntryEventBuilder(String className) { 96 return Event.builder(JDWPConstants.EventKind.METHOD_ENTRY, TEST_SUSPEND_POLICY) 97 .setClassMatch(className); 98 } 99 100 /** 101 * Creates an {@link EventBuilder} for METHOD_EXIT event and sets a 102 * ClassMatch modifier. 103 * 104 * @param className a regular expression of class names matching the method 105 * exit events. 106 * @return a new {@link EventBuilder} 107 */ 108 protected EventBuilder createMethodExitEventBuilder(String className) { 109 return Event.builder(JDWPConstants.EventKind.METHOD_EXIT, TEST_SUSPEND_POLICY) 110 .setClassMatch(className); 111 } 112 113 /** 114 * Creates an {@link EventBuilder} for METHOD_EXIT_WITH_RETURN_VALUE event 115 * and sets a ClassMatch modifier. 116 * 117 * @param className a regular expression of class names matching the method 118 * exit events. 119 * @return a new {@link EventBuilder} 120 */ 121 protected EventBuilder createMethodExitWithReturnValueEventBuilder(String className) { 122 return Event 123 .builder(JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE, TEST_SUSPEND_POLICY) 124 .setClassMatch(className); 125 } 126 127 /** 128 * Creates an {@link EventBuilder} for THREAD_START event. 129 * 130 * @return a new {@link EventBuilder} 131 */ 132 protected EventBuilder createThreadStartBuilder() { 133 return Event.builder(JDWPConstants.EventKind.THREAD_START, TEST_SUSPEND_POLICY); 134 } 135 136 /** 137 * Creates an {@link EventBuilder} for THREAD_END event. 138 * 139 * @return a new {@link EventBuilder} 140 */ 141 protected EventBuilder createThreadEndBuilder() { 142 return Event.builder(JDWPConstants.EventKind.THREAD_END, TEST_SUSPEND_POLICY); 143 } 144 145 /** 146 * Creates an {@link EventBuilder} for FIELD_ACCESS event and sets a 147 * FieldOnly modifier. 148 * 149 * @param typeTag the type tag of the field's declaring class 150 * @param classSignature the field's declaring class signature 151 * @param fieldName the field name 152 * @return a new {@link EventBuilder} 153 */ 154 protected EventBuilder createFieldAccessEventBuilder(byte typeTag, 155 String classSignature, String fieldName) { 156 return createFieldEventBuilder(typeTag, classSignature, fieldName, false); 157 } 158 159 /** 160 * Creates an {@link EventBuilder} for FIELD_MODIFICATION event and sets a 161 * FieldOnly modifier. 162 * 163 * @param typeTag the type tag of the field's declaring class 164 * @param classSignature the field's declaring class signature 165 * @param fieldName the field name 166 * @return a new {@link EventBuilder} 167 */ 168 protected EventBuilder createFieldModificationEventBuilder(byte typeTag, 169 String classSignature, String fieldName) { 170 return createFieldEventBuilder(typeTag, classSignature, fieldName, true); 171 } 172 173 private EventBuilder createFieldEventBuilder(byte typeTag, 174 String typeSignature, 175 String fieldName, 176 boolean modification) { 177 byte eventKind; 178 if (modification) { 179 eventKind = JDWPConstants.EventKind.FIELD_MODIFICATION; 180 } else { 181 eventKind = JDWPConstants.EventKind.FIELD_ACCESS; 182 } 183 long typeID = debuggeeWrapper.vmMirror.getTypeID(typeSignature, typeTag); 184 assertTrue("Failed to find type ID " + typeSignature, typeID != 1); 185 long fieldID = debuggeeWrapper.vmMirror.getFieldID(typeID, fieldName); 186 assertTrue("Failed to find field ID " + typeSignature + "." + fieldName, 187 fieldID != 1); 188 return Event.builder(eventKind, TEST_SUSPEND_POLICY).setFieldOnly(typeID, fieldID); 189 } 190 191 /** 192 * Sends a request for the given event. 193 * 194 * @param event the event to request 195 * @return the request ID 196 */ 197 protected int requestEvent(Event event) { 198 String eventName = JDWPConstants.EventKind.getName(event.eventKind); 199 logWriter.println("Requesting " + eventName); 200 ReplyPacket reply = debuggeeWrapper.vmMirror.setEvent(event); 201 checkReplyPacket(reply, "Failed to request " + eventName); 202 int requestID = reply.getNextValueAsInt(); 203 assertAllDataRead(reply); 204 return requestID; 205 } 206 207 /** 208 * Waits for the first corresponding event. 209 * 210 * @param eventKind the event kind 211 * @param requestID the event request ID 212 * @return the event 213 */ 214 protected EventThread waitForEvent(byte eventKind, int requestID) { 215 logWriter.println("Signaling debuggee to continue"); 216 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 217 218 String eventName = JDWPConstants.EventKind.getName(eventKind); 219 logWriter.println( 220 "Waiting for " + eventName + " with requestID " + requestID + " ..."); 221 EventPacket eventPacket = debuggeeWrapper.vmMirror.receiveCertainEvent( 222 eventKind); 223 ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket); 224 assertNotNull(parsedEvents); 225 assertTrue(parsedEvents.length > 0); 226 ParsedEvent event = parsedEvents[0]; 227 assertEquals(eventKind, event.getEventKind()); 228 assertEquals(requestID, event.getRequestID()); 229 logWriter.println("Received " + eventName + " event"); 230 return (EventThread) event; 231 } 232 233 /** 234 * Clears the corresponding event and resumes the VM. 235 * 236 * @param eventKind the event kind 237 * @param requestID the event request ID 238 */ 239 protected void clearAndResume(byte eventKind, int requestID) { 240 clearEvent(eventKind, requestID, true); 241 resumeDebuggee(); 242 } 243 244 /** 245 * Warns about an unsupported capability by printing a message in the 246 * console. 247 * 248 * @param capabilityName the capability name 249 */ 250 protected void logCapabilityWarning(String capabilityName) { 251 // Build the message to prompt. 252 StringBuilder messageBuilder = 253 new StringBuilder("# WARNING: this VM doesn't possess capability: "); 254 messageBuilder.append(capabilityName); 255 messageBuilder.append(' '); 256 messageBuilder.append('#'); 257 String message = messageBuilder.toString(); 258 259 // Build a sharp string long enough. 260 int sharpLineLength = message.length(); 261 StringBuilder sharpLineBuilder = new StringBuilder(sharpLineLength); 262 for (int i = 0; i < sharpLineLength; ++i) { 263 sharpLineBuilder.append('#'); 264 } 265 String sharpLine = sharpLineBuilder.toString(); 266 267 // Print warning message. 268 logWriter.println(sharpLine); 269 logWriter.println(message); 270 logWriter.println(sharpLine); 271 } 272} 273