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  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 /**
19  * @author Anatoly F. Bondarenko
20  */
21 
22 /**
23  * Created on 26.10.2006
24  */
25 package org.apache.harmony.jpda.tests.jdwp.Events;
26 
27 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
28 import org.apache.harmony.jpda.tests.framework.jdwp.EventMod;
29 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
30 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
31 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
32 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
33 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
34 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
35 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
36 
37 /**
38  * JDWP Unit test for possible combined (co-located) events:
39  * METHOD_ENTRY, SINGLE_STEP, BREAKPOINT, METHOD_EXIT.
40  */
41 public class CombinedEvents003Test extends CombinedEventsTestCase {
42 
43     private String debuggeeSignature =
44         "Lorg/apache/harmony/jpda/tests/jdwp/Events/CombinedEvents003Debuggee;";
45 
46     private String methodForEvents = "emptyMethod";
47 
48     private String methodEntryClassNameRegexp =
49         "org.apache.harmony.jpda.tests.jdwp.Events.CombinedEvents003Debuggee";
50 
51     private boolean eventVmDeathReceived = false;
52 
getDebuggeeClassName()53     protected String getDebuggeeClassName() {
54         return CombinedEvents003Debuggee.class.getName();
55     }
56 
57     /**
58      * This test case checks events:
59      * METHOD_ENTRY, SINGLE_STEP, BREAKPOINT, METHOD_EXIT
60      * for empty method.
61      */
62 
testCombinedEvents003_01()63     public void testCombinedEvents003_01() {
64         logWriter.println("==> testCombinedEvents003_01 started");
65 
66         byte[] EXPECTED_EVENTS_ARRAY = { JDWPConstants.EventKind.METHOD_ENTRY,
67                 JDWPConstants.EventKind.BREAKPOINT,
68                 JDWPConstants.EventKind.SINGLE_STEP,
69                 JDWPConstants.EventKind.METHOD_EXIT};
70 
71         String debuggeeMainThreadName = synchronizer.receiveMessage();
72 
73         long debuggeeClassID = debuggeeWrapper.vmMirror
74                 .getClassID(debuggeeSignature);
75         logWriter.println("=> debuggeeClassID = " + debuggeeClassID);
76 
77         long threadID = debuggeeWrapper.vmMirror.getThreadID(debuggeeMainThreadName);
78         logWriter.println("=> threadID = " + threadID);
79 
80         long runMethodID = debuggeeWrapper.vmMirror.getMethodID(debuggeeClassID, "run");
81         logWriter.println("=> runMethodID = " + runMethodID);
82 
83         long dummyMethodID = debuggeeWrapper.vmMirror.getMethodID(debuggeeClassID, "dummyMethod");
84         logWriter.println("=> dummyMethodID = " + dummyMethodID);
85 
86         logWriter.println("");
87         logWriter.println("=> Info for tested method '" + methodForEvents + "':");
88         long testedMethodID = debuggeeWrapper.vmMirror.getMethodID(debuggeeClassID, methodForEvents);
89         if (testedMethodID == -1 ) {
90             String failureMessage = "## FAILURE: Can NOT get MethodID for class '"
91                 + getDebuggeeClassName() + "'; Method name = " + methodForEvents;
92             printErrorAndFail(failureMessage);
93         }
94         logWriter.println("=> testedMethodID = " + testedMethodID);
95         printMethodLineTable(debuggeeClassID, null, methodForEvents);
96 
97         // set requests for events that will be checked
98         logWriter.println("");
99         logWriter.println("=> Set request for BREAKPOINT event in debuggee: "
100                 + getDebuggeeClassName() + ", beginning of method: "
101                 + methodForEvents);
102         Location combinedEventsLocation = getMethodEntryLocation(debuggeeClassID, methodForEvents);
103         if ( combinedEventsLocation == null ) {
104             String failureMessage = "## FAILURE: Can NOT get MethodEntryLocation for method '"
105                 + methodForEvents + "'";
106             printErrorAndFail(failureMessage);
107         }
108         ReplyPacket reply = debuggeeWrapper.vmMirror.setBreakpoint(combinedEventsLocation);
109         int breakpointRequestID = reply.getNextValueAsInt();
110         logWriter.println("=> Breakpoint requestID = " + breakpointRequestID);
111 
112         logWriter.println("=> Set request for METHOD_ENTRY event in debuggee: "
113                 + getDebuggeeClassName());
114         reply = debuggeeWrapper.vmMirror
115                 .setMethodEntry(methodEntryClassNameRegexp);
116         checkReplyPacket(reply, "Set METHOD_ENTRY event");
117         int methodEntryRequestID = reply.getNextValueAsInt();
118         logWriter.println("=> METHOD_ENTRY requestID = " + methodEntryRequestID);
119         logWriter.println("=> Set request for METHOD_EXIT event in debuggee: "
120                 + getDebuggeeClassName());
121         reply = debuggeeWrapper.vmMirror
122                 .setMethodExit(methodEntryClassNameRegexp);
123         checkReplyPacket(reply, "Set METHOD_EXIT event");
124         int methodExitRequestID = reply.getNextValueAsInt();
125         logWriter.println("=> METHOD_EXIT requestID = " + methodExitRequestID);
126 
127         logWriter.println("=> Set request for SINGLE_STEP event in class "
128                 + debuggeeSignature);
129         CommandPacket setRequestCommand = new CommandPacket(
130                 JDWPCommands.EventRequestCommandSet.CommandSetID,
131                 JDWPCommands.EventRequestCommandSet.SetCommand);
132         setRequestCommand
133                 .setNextValueAsByte(JDWPConstants.EventKind.SINGLE_STEP);
134         setRequestCommand.setNextValueAsByte(JDWPConstants.SuspendPolicy.ALL);
135         setRequestCommand.setNextValueAsInt(2);
136         setRequestCommand.setNextValueAsByte(EventMod.ModKind.Step);
137         setRequestCommand.setNextValueAsThreadID(threadID);
138         setRequestCommand.setNextValueAsInt(JDWPConstants.StepSize.MIN);
139         setRequestCommand.setNextValueAsInt(JDWPConstants.StepDepth.INTO);
140         setRequestCommand.setNextValueAsByte(EventMod.ModKind.ClassOnly);
141         setRequestCommand.setNextValueAsReferenceTypeID(debuggeeClassID);
142 
143         ReplyPacket setRequestReply = debuggeeWrapper.vmMirror
144                 .performCommand(setRequestCommand);
145         checkReplyPacket(setRequestReply, "EventRequest::Set command");
146         int stepRequestID = setRequestReply.getNextValueAsInt();
147         logWriter.println("=> SINGLE_STEP requestID = " + stepRequestID);
148 
149         logWriter.println("");
150         logWriter.println("=> Send SGNL_CONTINUE signal to debuggee...");
151         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
152 
153         logWriter.println("=> Try to receive and check combined events: "
154             + " METHOD_ENTRY, SINGLE_STEP, BREAKPOINT, METHOD_EXIT events; ignore single SINGLE_STEP event");
155         receiveAndCheckEvents(EXPECTED_EVENTS_ARRAY, combinedEventsLocation);
156         if ( eventVmDeathReceived ) {
157             logWriter.println("==> testCombinedEvents001 is FINISHing as VM_DEATH is received!");
158             return;
159         }
160 
161         logWriter.println("");
162         logWriter.println("=> Clean request for METHOD_ENTRY event...");
163         ReplyPacket clearReply = debuggeeWrapper.vmMirror.clearEvent(
164                 JDWPConstants.EventKind.METHOD_ENTRY, methodEntryRequestID);
165         checkReplyPacket(clearReply, "EventRequest::Clear");
166 
167         logWriter.println("");
168         logWriter.println("=> Clean request for SINGLE_STEP event...");
169         clearReply = debuggeeWrapper.vmMirror.clearEvent(
170                 JDWPConstants.EventKind.SINGLE_STEP, stepRequestID);
171         checkReplyPacket(clearReply, "EventRequest::Clear");
172 
173         logWriter.println("=> Resume debuggee");
174         debuggeeWrapper.vmMirror.resume();
175 
176         // check that no other events, except VM_DEATH, will be received
177         checkVMDeathEvent();
178 
179         logWriter.println("");
180         logWriter.println("==> testCombinedEvents003_01 PASSED");
181     }
182 
receiveAndCheckEvents(byte[] EXPECTED_EVENTS_ARRAY, Location expectedLocation)183     void receiveAndCheckEvents(byte[] EXPECTED_EVENTS_ARRAY, Location expectedLocation) {
184         int EXPECTED_EVENTS_COUNT = EXPECTED_EVENTS_ARRAY.length;
185         for (;;) {
186             logWriter.println("=>");
187             logWriter.println("=> Receiving events...");
188             EventPacket event = debuggeeWrapper.vmMirror.receiveEvent();
189             ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event);
190 
191             // print all received events
192             logWriter.println("=> Received event packet with events number = " + parsedEvents.length + " :");
193 
194             for (int i = 0; i < parsedEvents.length; i++) {
195                 logWriter.println("");
196                 logWriter.println("=> Event #" + (i+1) + " in packet -");
197                 logWriter.println("=> EventKind: "
198                         + parsedEvents[i].getEventKind()
199                         + "["
200                         + JDWPConstants.EventKind.getName(parsedEvents[i]
201                                 .getEventKind()) + "]");
202                 logWriter.println("=> RequestID: "
203                         + parsedEvents[i].getRequestID());
204                 if ( parsedEvents[i].getEventKind() == JDWPConstants.EventKind.VM_DEATH ) {
205                     eventVmDeathReceived = true;
206                 }
207             }
208             if ( eventVmDeathReceived ) {
209                 return;
210             }
211             checkEventsLocation(parsedEvents, null); // DBG__
212 
213             // the following code checks received events
214             if (parsedEvents.length == 1) {
215                 debuggeeWrapper.vmMirror.resume();
216                 continue;
217 /* DBG__
218                 if (parsedEvents[0].getEventKind() == JDWPConstants.EventKind.SINGLE_STEP) {
219                     logWriter.println("");
220                     logWriter.println("=> Resume debuggee");
221                     logWriter.println("");
222                     debuggeeWrapper.vmMirror.resume();
223                     continue;
224                 } else {
225                     logWriter.println("##FAILURE: received unexpected event: "
226                             + parsedEvents[0].getEventKind()
227                             + "["
228                             + JDWPConstants.EventKind.getName(parsedEvents[0]
229                                     .getEventKind())
230                             + "] instead of SINGLE_STEP");
231                     fail("received event is not SINGLE_STEP event: "
232                             + parsedEvents[0].getEventKind()
233                             + "["
234                             + JDWPConstants.EventKind.getName(parsedEvents[0]
235                                     .getEventKind()) + "]");
236                 }
237 // DBG__ */
238             //DBG__} else if (parsedEvents.length == EXPECTED_EVENTS_COUNT) {
239             } else if (parsedEvents.length > 1) {
240                 logWriter.println("");
241                 logWriter
242                         .println("=> Combined events are received. Check events..");
243                 boolean success = true;
244                 for (int i = 0; i < parsedEvents.length; i++) {
245                     boolean isFound = false;
246                     for (int j = 0; j < EXPECTED_EVENTS_COUNT; j++) {
247                         if (parsedEvents[i].getEventKind() == EXPECTED_EVENTS_ARRAY[j]) {
248                             EXPECTED_EVENTS_ARRAY[j] = 0;
249                             isFound = true;
250                             break;
251                         }
252                     }
253                     if (!isFound) {
254                         logWriter.println("##FAILURE: received unexpected event: "
255                                         + parsedEvents[i].getEventKind()
256                                         + "["
257                                         + JDWPConstants.EventKind
258                                                 .getName(parsedEvents[0]
259                                                         .getEventKind()) + "]");
260                         success = false;
261                     }
262                 }
263                 if (!success) {
264                     logWriter.println("");
265                     logWriter.println("##FAILURE: the following expected events were not received: ");
266                     for (int k = 0; k < EXPECTED_EVENTS_COUNT; k++) {
267                         if (EXPECTED_EVENTS_ARRAY[k] != 0)
268                             logWriter.println("  #"
269                                     + k
270                                     + ": "
271                                     + EXPECTED_EVENTS_ARRAY[k]
272                                     + "["
273                                     + JDWPConstants.EventKind
274                                             .getName(EXPECTED_EVENTS_ARRAY[k])
275                                     + "]");
276                     }
277                     fail("not all expected events were received");
278                 }
279                 for (int i = 0; i < parsedEvents.length; i++) {
280                     byte eventKind = parsedEvents[i].getEventKind();
281                     long eventThreadID = ((ParsedEvent.EventThread)parsedEvents[i]).getThreadID();
282                     logWriter.println("");
283                     logWriter.println("=> Chcek location for combined event N " + (i+1)
284                         + ": Event kind = " + eventKind + "("
285                         + JDWPConstants.EventKind.getName(eventKind) +"); eventThreadID = "
286                         + eventThreadID);
287                     Location eventLocation = null;
288                     switch ( eventKind ) {
289                     case JDWPConstants.EventKind.METHOD_ENTRY:
290                         eventLocation = ((ParsedEvent.Event_METHOD_ENTRY)parsedEvents[i]).getLocation();
291                         break;
292                     case JDWPConstants.EventKind.SINGLE_STEP:
293                         eventLocation = ((ParsedEvent.Event_SINGLE_STEP)parsedEvents[i]).getLocation();
294                         break;
295                     case JDWPConstants.EventKind.BREAKPOINT:
296                         eventLocation = ((ParsedEvent.Event_BREAKPOINT)parsedEvents[i]).getLocation();
297                         break;
298                     case JDWPConstants.EventKind.METHOD_EXIT:
299                         eventLocation = ((ParsedEvent.Event_METHOD_EXIT)parsedEvents[i]).getLocation();
300                         break;
301                     }
302                     long eventClassID = eventLocation.classID;
303                     logWriter.println("=> ClassID in event = " + eventClassID);
304                     if ( expectedLocation.classID != eventClassID ) {
305                         logWriter.println("## FAILURE: Unexpected ClassID in event!");
306                         logWriter.println("##          Expected ClassID  = " + expectedLocation.classID );
307                         success = false;
308                     } else {
309                         logWriter.println("=> OK - it is expected ClassID");
310                     }
311                     long eventMethodID = eventLocation.methodID;
312                     logWriter.println("=> MethodID in event = " + eventMethodID);
313                     if ( expectedLocation.methodID != eventMethodID ) {
314                         logWriter.println("## FAILURE: Unexpected MethodID in event!");
315                         logWriter.println("##          Expected MethodID = " + expectedLocation.methodID);
316                         success = false;
317                     } else {
318                         logWriter.println("=> OK - it is expected MethodID");
319                     }
320                     long eventCodeIndex = eventLocation.index;
321                     logWriter.println("=> CodeIndex in event = " + eventCodeIndex);
322                     if ( expectedLocation.index != eventCodeIndex ) {
323                         logWriter.println("## FAILURE: Unexpected CodeIndex in event!");
324                         logWriter.println("##          Expected CodeIndex = "
325                             + expectedLocation.index);
326                         success = false;
327                     } else {
328                         logWriter.println("=> OK - it is expected CodeIndex)");
329                     }
330                 }
331                 logWriter.println("");
332                 if ( ! success ) {
333                     String failureMessage = "## FAILURE: Unexpected events' locations are found out!";
334                     logWriter.println(failureMessage);
335                     //DBG__printErrorAndFail(failureMessage);
336                 } else {
337                     logWriter.println("=> OK - all combined events have expected location!");
338                 }
339                 break;
340             } else {
341                 logWriter.println("##FAILURE: received unexpected number of events: "
342                                 + parsedEvents.length
343                                 + " instead of 1 or "
344                                 + EXPECTED_EVENTS_COUNT);
345                 fail("received unexpected number of events: "
346                         + parsedEvents.length);
347             }
348         }
349     }
350 
checkVMDeathEvent()351     void checkVMDeathEvent() {
352         if ( eventVmDeathReceived ) {
353             return;
354         }
355         logWriter.println("=> Wait for VM_DEATH event...");
356         while ( true ) { //DBG_
357             logWriter.println("=> Receiving events...");
358             EventPacket event = debuggeeWrapper.vmMirror.receiveEvent();
359             ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event);
360             if (parsedEvents.length != 1
361                     || parsedEvents[0].getEventKind() != JDWPConstants.EventKind.VM_DEATH) {
362                 // print all received events
363                 logWriter.println("##FAILURE: Received unexpected events");
364                 logWriter.println("=> Events received: " + parsedEvents.length);
365                 for (int i = 0; i < parsedEvents.length; i++) {
366                     logWriter.println("");
367                     logWriter.println("=> Event #" + i + ";");
368                     logWriter.println("=> EventKind: "
369                             + parsedEvents[i].getEventKind()
370                             + "["
371                             + JDWPConstants.EventKind.getName(parsedEvents[i]
372                                     .getEventKind()) + "]");
373                     logWriter.println("=> RequestID: "
374                             + parsedEvents[i].getRequestID());
375                 }
376                 checkEventsLocation(parsedEvents, null); // DBG__
377                 logWriter.println("=> Resume debuggee"); //DBG__
378                 debuggeeWrapper.vmMirror.resume(); //DBG__
379                 continue; //DBG__
380                 //DBG__fail("unexpected events received");
381             }
382             logWriter.println("=> OK - VM_DEATH event was received. ");
383             break; //DBG__
384         } // DBG__
385     }
386 }
387