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