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