• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18 
19 /**
20  * @author Anatoly F. Bondarenko
21  */
22 
23 /**
24  * Created on 06.10.2006
25  */
26 package org.apache.harmony.jpda.tests.jdwp.Events;
27 
28 import org.apache.harmony.jpda.tests.framework.TestErrorException;
29 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
30 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
31 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
32 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
33 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
34 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
35 
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 
42 
43 /**
44  * JDWP Unit test for METHOD_ENTRY, METHOD_EXIT events for empty method.
45  */
46 public class CombinedEvents002Test extends CombinedEventsTestCase {
47     static final String TESTED_CLASS_NAME =
48         CombinedEvents002Debuggee.TESTED_CLASS_NAME;
49     static final String TESTED_CLASS_SIGNATURE =
50         CombinedEvents002Debuggee.TESTED_CLASS_SIGNATURE;
51     static final String TESTED_METHOD_NAME = CombinedEvents002Debuggee.TESTED_METHOD_NAME;
52 
53     private long testedClassID = -1;
54     private long testedMethodID = -1;
55     private long testedMethodStartCodeIndex = -1;
56     private long testedMethodEndCodeIndex = -1;
57     private Map<Byte, Integer> requestsMap = new HashMap<>();
58 
59     @Override
getDebuggeeClassName()60     protected String getDebuggeeClassName() {
61         return CombinedEvents002Debuggee.class.getName();
62     }
63 
64     /**
65      * This testcase is for METHOD_ENTRY, METHOD_EXIT events for empty method.
66      * <BR>It runs CombinedEvents002Debuggee that executed its own empty method
67      * and verify that requested METHOD_ENTRY, METHOD_EXIT events occur
68      * for empty method.
69      */
testCombinedEvents002_01()70     public void testCombinedEvents002_01() {
71         byte[] expectedEventKinds = {
72                 JDWPConstants.EventKind.METHOD_ENTRY,
73                 JDWPConstants.EventKind.METHOD_EXIT
74         };
75         runTest(expectedEventKinds);
76     }
77 
78     /**
79      * This testcase is for METHOD_ENTRY, METHOD_EXIT_WITH_RETURN_VALUE events for empty method.
80      * <BR>It runs CombinedEvents002Debuggee that executed its own empty method
81      * and verify that requested METHOD_ENTRY, METHOD_EXIT_WITH_RETURN_VALUE events occur
82      * for empty method.
83      */
testCombinedEvents002_02()84     public void testCombinedEvents002_02() {
85         byte[] expectedEventKinds = {
86                 JDWPConstants.EventKind.METHOD_ENTRY,
87                 JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE
88         };
89         runTest(expectedEventKinds);
90     }
91 
runTest(byte[] expectedEventKinds)92     private void runTest(byte[] expectedEventKinds) {
93         logWriter.println("==> " + getName() + ": Start...");
94 
95         prepareDebuggee(expectedEventKinds);
96         List<ParsedEvent> receivedEvents = receiveEvents();
97         checkEvents(receivedEvents, expectedEventKinds);
98         clearEvents();
99 
100         logWriter.println("==> Resume debuggee VM...");
101         debuggeeWrapper.vmMirror.resume();
102         logWriter.println("==> " + getName() + ": PASSED! ");
103     }
104 
105     /**
106      * Computes JDWP ids and requests events.
107      */
prepareDebuggee(byte[] expectedEventKinds)108     private void prepareDebuggee(byte[] expectedEventKinds) {
109         logWriter.println("==> Wait for SGNL_READY signal from debuggee...");
110         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
111         logWriter.println("==> OK - SGNL_READY signal received!");
112 
113         testedClassID =
114             debuggeeWrapper.vmMirror.getClassID(TESTED_CLASS_SIGNATURE);
115         if ( testedClassID == -1 ) {
116             String failureMessage = "## FAILURE: Can NOT get ClassID for '"
117                 + TESTED_CLASS_SIGNATURE + "'";
118             printErrorAndFail(failureMessage);
119         }
120         logWriter.println("==> Tested Class Name = '" + TESTED_CLASS_NAME + "'");
121         logWriter.println("==> testedClassID = " + testedClassID);
122 
123         logWriter.println("==> ");
124         logWriter.println("==> Info for tested method '" + TESTED_METHOD_NAME + "':");
125         testedMethodID = debuggeeWrapper.vmMirror.getMethodID(testedClassID, TESTED_METHOD_NAME);
126         if (testedMethodID == -1 ) {
127             String failureMessage = "## FAILURE: Can NOT get MethodID for class '"
128                 + TESTED_CLASS_NAME + "'; Method name = " + TESTED_METHOD_NAME;
129             printErrorAndFail(failureMessage);
130         }
131         logWriter.println("==> testedMethodID = " + testedMethodID);
132         printMethodLineTable(testedClassID, null, TESTED_METHOD_NAME);
133         testedMethodStartCodeIndex = getMethodStartCodeIndex(testedClassID, TESTED_METHOD_NAME);
134         if ( testedMethodStartCodeIndex == -1 ) {
135             String failureMessage = "## FAILURE: Can NOT get MethodStartCodeIndex for method '"
136                 + TESTED_METHOD_NAME + "' ";
137             printErrorAndFail(failureMessage);
138         }
139         testedMethodEndCodeIndex = getMethodEndCodeIndex(testedClassID, TESTED_METHOD_NAME);
140         if ( testedMethodEndCodeIndex == -1 ) {
141             String failureMessage = "## FAILURE: Can NOT get MethodEndCodeIndex for method '"
142                 + TESTED_METHOD_NAME + "' ";
143             printErrorAndFail(failureMessage);
144         }
145 
146         // Request events.
147         for (byte eventKind : expectedEventKinds) {
148             String eventKindName = JDWPConstants.EventKind.getName(eventKind);
149             logWriter.println("==> ");
150             logWriter.println("==> Set request for " + eventKindName +
151                     " event for '" + TESTED_CLASS_NAME + "'... ");
152             ReplyPacket reply = null;
153             switch (eventKind) {
154                 case JDWPConstants.EventKind.METHOD_ENTRY:
155                     reply = debuggeeWrapper.vmMirror.setMethodEntry(TESTED_CLASS_NAME);
156                     break;
157                 case JDWPConstants.EventKind.METHOD_EXIT:
158                     reply = debuggeeWrapper.vmMirror.setMethodExit(TESTED_CLASS_NAME);
159                     break;
160                 case JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
161                     reply =
162                         debuggeeWrapper.vmMirror.setMethodExitWithReturnValue(TESTED_CLASS_NAME);
163                     break;
164                 default:
165                     throw new TestErrorException("Unexpected event: " + eventKindName);
166             }
167             checkReplyPacket(reply, "Set " + eventKindName + " event.");  //DBG needless ?
168             int requestId = reply.getNextValueAsInt();
169             requestsMap.put(Byte.valueOf(eventKind), Integer.valueOf(requestId));
170             logWriter.println("==> OK - request " + requestId + " for " + eventKind +
171                     " event is set!");
172         }
173 
174         logWriter.println("==> Send SGNL_CONTINUE signal to debuggee...");
175         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
176     }
177 
178     /**
179      * Receives events from the debuggee
180      */
receiveEvents()181     private List<ParsedEvent> receiveEvents() {
182         List<ParsedEvent> receivedEvents = new ArrayList<ParsedEvent>();
183         logWriter.println("==> ");
184         logWriter.println("==> Receiving events... ");
185         CommandPacket event = debuggeeWrapper.vmMirror.receiveEvent();
186         ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event);
187 
188         int receivedEventsNumber = parsedEvents.length;
189         logWriter.println("==> Number of received events in event packet = " + receivedEventsNumber);
190         for (int i = 0; i < receivedEventsNumber; ++i) {
191             receivedEvents.add(parsedEvents[i]);
192 
193             byte eventKind = parsedEvents[i].getEventKind();
194             eventKind = parsedEvents[i].getEventKind();
195             logWriter.println("==> Received event[" + i + "] kind = "
196                 +  eventKind
197                 + "(" + JDWPConstants.EventKind.getName(eventKind) + ")");
198         }
199         if (receivedEventsNumber > 2) {
200             String failureMessage = "## FAILURE: Unexpected number of received events in packet = "
201                 + receivedEventsNumber + "\n## Expected number of received events in packet = 1 or 2";
202             printErrorAndFail(failureMessage);
203         }
204         if (receivedEventsNumber == 1) {
205             logWriter.println("==> ");
206             logWriter.println("==> Resume debuggee VM...");
207             debuggeeWrapper.vmMirror.resume();
208             logWriter.println("==> Receiving events... ");
209             event = debuggeeWrapper.vmMirror.receiveEvent();
210             parsedEvents = ParsedEvent.parseEventPacket(event);
211 
212             receivedEventsNumber = parsedEvents.length;
213             logWriter.println("==> Number of received events in event packet = " + receivedEventsNumber);
214             for (int i = 0; i < receivedEventsNumber; ++i) {
215                 receivedEvents.add(parsedEvents[i]);
216 
217                 byte eventKind = parsedEvents[i].getEventKind();
218                 logWriter.println("==> Received event[" + i + "] kind = "
219                     +  eventKind
220                     + "(" + JDWPConstants.EventKind.getName(eventKind) + ")");
221             }
222             if (receivedEventsNumber != 1) {
223                 String failureMessage = "## FAILURE: Unexpected number of received events in packet = "
224                     + receivedEventsNumber + "\n## Expected number of received events in packet = 1";
225                 printErrorAndFail(failureMessage);
226             }
227         }
228         return receivedEvents;
229     }
230 
231     /**
232      * Checks we received expected events from the debuggee.
233      */
checkEvents(List<ParsedEvent> receivedEvents, byte[] expectedEventKinds)234     private void checkEvents(List<ParsedEvent> receivedEvents,
235             byte[] expectedEventKinds) {
236         boolean testCaseIsOk = true;
237         byte[] receivedEventKinds = new byte[receivedEvents.size()];
238         for (int i = 0, e = receivedEvents.size(); i < e; ++i) {
239             logWriter.println("==> ");
240             logWriter.println("==> Check received event #" + i + "...");
241             ParsedEvent parsedEvent = receivedEvents.get(i);
242             byte eventKind = parsedEvent.getEventKind();
243             receivedEventKinds[i] = eventKind;
244             switch (eventKind) {
245             case JDWPConstants.EventKind.METHOD_ENTRY:
246                 testCaseIsOk &= checkMethodEntryEvent(parsedEvent);
247                 break;
248             case JDWPConstants.EventKind.METHOD_EXIT:
249                 testCaseIsOk &= checkMethodExitEvent(parsedEvent);
250                 break;
251             case JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
252                 testCaseIsOk &= checkMethodExitWithReturnValueEvent(parsedEvent);
253                 break;
254             }
255         }
256         if (!testCaseIsOk) {
257             String failureMessage = "## FAILURE: Unexpected events attributes are found out!";
258             printErrorAndFail(failureMessage);
259         }
260 
261         // Check that we received all expected events.
262         Arrays.sort(expectedEventKinds);
263         Arrays.sort(receivedEventKinds);
264         if (!Arrays.equals(expectedEventKinds, receivedEventKinds)) {
265             String failureMessage = "## FAILURE: Did not receive all expected events!";
266             printErrorAndFail(failureMessage);
267         }
268     }
269 
checkMethodEntryEvent(ParsedEvent parsedEvent)270     private boolean checkMethodEntryEvent(ParsedEvent parsedEvent) {
271         ParsedEvent.Event_METHOD_ENTRY methodEntryEvent =
272                 (ParsedEvent.Event_METHOD_ENTRY) parsedEvent;
273         Location expectedLocation = new Location(JDWPConstants.TypeTag.CLASS, testedClassID,
274                 testedMethodID, testedMethodStartCodeIndex);
275         return checkEventLocation(methodEntryEvent, expectedLocation);
276     }
277 
checkMethodExitEvent(ParsedEvent parsedEvent)278     private boolean checkMethodExitEvent(ParsedEvent parsedEvent) {
279         ParsedEvent.Event_METHOD_EXIT methodExitEvent =
280                 (ParsedEvent.Event_METHOD_EXIT) parsedEvent;
281         Location expectedLocation = new Location(JDWPConstants.TypeTag.CLASS, testedClassID,
282                 testedMethodID, testedMethodEndCodeIndex);
283         return checkEventLocation(methodExitEvent, expectedLocation);
284     }
285 
checkMethodExitWithReturnValueEvent(ParsedEvent parsedEvent)286     private boolean checkMethodExitWithReturnValueEvent(ParsedEvent parsedEvent) {
287         ParsedEvent.Event_METHOD_EXIT_WITH_RETURN_VALUE methodExitWithReturnValueEvent =
288                 (ParsedEvent.Event_METHOD_EXIT_WITH_RETURN_VALUE) parsedEvent;
289         Location expectedLocation = new Location(JDWPConstants.TypeTag.CLASS, testedClassID,
290                 testedMethodID, testedMethodEndCodeIndex);
291         boolean result = checkEventLocation(methodExitWithReturnValueEvent, expectedLocation);
292         // Expect null return value because method is 'void'.
293         if (methodExitWithReturnValueEvent.getReturnValue() != null) {
294             logWriter.println("## FAILURE: Unexpected return value in event!");
295             logWriter.println("##          Expected null");
296             result = false;
297         } else {
298             logWriter.println("==> OK - it is expected return value tag");
299         }
300         return result;
301     }
302 
303     /**
304      * Clear event requests.
305      */
clearEvents()306     private void clearEvents() {
307         for (Byte eventKind : requestsMap.keySet()) {
308             Integer requestId = requestsMap.get(eventKind);
309             logWriter.println("==> ");
310             logWriter.println("==> Clear request " + requestId.intValue() + " for " +
311                     JDWPConstants.EventKind.getName(eventKind.byteValue()));
312             debuggeeWrapper.vmMirror.clearEvent(eventKind.byteValue(), requestId.intValue());
313         }
314         requestsMap.clear();
315     }
316 }
317