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