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 package org.apache.harmony.jpda.tests.jdwp.Events; 20 21 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket; 22 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 23 import org.apache.harmony.jpda.tests.framework.jdwp.Location; 24 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent; 25 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 26 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 27 28 /** 29 * JDWP Unit test for SINGLE_STEP event with pending exception. 30 */ 31 public class SingleStepWithPendingExceptionTest extends JDWPEventTestCase { 32 33 @Override 34 protected String getDebuggeeClassName() { 35 return SingleStepWithPendingExceptionDebuggee.class.getName(); 36 } 37 38 /** 39 * Tests that we properly single-step OUT of a method throwing an exception 40 * to a catch handler. 41 * 42 * We execute the test method once with an EXCEPTION event request to capture the 43 * location of the catch handler. 44 * Then we set a BREAKPOINT event in the method throwing the exception and execute 45 * the test method another time. We wait for hitting the breakpoint then we issue 46 * a SINGLE_STEP OUT request and check that we stop in the catch handler. 47 */ 48 public void testSingleStepWithPendingException() { 49 logWriter.println("=> testSingleStepWithPendingException started"); 50 51 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 52 53 // Find debuggee class id. 54 long refTypeID = getClassIDBySignature(getDebuggeeClassSignature()); 55 logWriter.println("=> Debuggee class = " + getDebuggeeClassName()); 56 logWriter.println("=> referenceTypeID for Debuggee class = " + refTypeID); 57 58 long catchMethodId = getMethodID(refTypeID, "catchMethod"); 59 60 // Request exception event. 61 int exceptionRequestId = setCatchException(); 62 63 // Resume debuggee so we hit the breakpoint. 64 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 65 66 // Wait for exception and remember catch location. 67 EventPacket eventPacket = 68 debuggeeWrapper.vmMirror.receiveCertainEvent(JDWPConstants.EventKind.EXCEPTION); 69 ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket); 70 assertEquals("Expected only one event", 1, parsedEvents.length); 71 assertEventKindEquals("Expected EXCEPTION event", parsedEvents[0].getEventKind(), 72 JDWPConstants.EventKind.EXCEPTION); 73 assertEquals("Unexpected event", exceptionRequestId, parsedEvents[0].getRequestID()); 74 Location catchHandlerLocation = 75 ((ParsedEvent.Event_EXCEPTION)parsedEvents[0]).getCatchLocation(); 76 assertEquals("Invalid location's class", refTypeID, catchHandlerLocation.classID); 77 assertEquals("Invalid location's method", catchMethodId, catchHandlerLocation.methodID); 78 79 // Remove exception request. 80 clearEvent(JDWPConstants.EventKind.EXCEPTION, exceptionRequestId, true); 81 82 // Install breakpoint at begin of throwMethod. 83 int breakpointRequestId = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(refTypeID, 84 "throwMethod"); 85 86 // Exception event suspended all threads: resume them now. 87 debuggeeWrapper.resume(); 88 89 // Wait for breakpoint. 90 long threadId = debuggeeWrapper.vmMirror.waitForBreakpoint(breakpointRequestId); 91 92 // Single-step OUT of the throwMethod. 93 int singleStepRequestId = setSingleStepOut(threadId); 94 95 // Breakpoint event suspended all threads: resume them now. 96 debuggeeWrapper.resume(); 97 98 // Wait for single-step. 99 eventPacket = 100 debuggeeWrapper.vmMirror.receiveCertainEvent(JDWPConstants.EventKind.SINGLE_STEP); 101 parsedEvents = ParsedEvent.parseEventPacket(eventPacket); 102 assertEquals("Expected only one event", 1, parsedEvents.length); 103 assertEventKindEquals("Expected SINGLE_STEP event", parsedEvents[0].getEventKind(), 104 JDWPConstants.EventKind.SINGLE_STEP); 105 106 // Check that we reached the catch handler location. 107 Location singleStepLocation = 108 ((ParsedEvent.Event_SINGLE_STEP)parsedEvents[0]).getLocation(); 109 if (!catchHandlerLocation.equals(singleStepLocation)) { 110 fail("Invalid single-step location: expected " + catchHandlerLocation + 111 " but was " + singleStepLocation); 112 } 113 114 // Remove single-step request. 115 clearEvent(JDWPConstants.EventKind.SINGLE_STEP, singleStepRequestId, true); 116 117 logWriter.println("==> Resuming debuggee"); 118 resumeDebuggee(); 119 logWriter.println("==> testSingleStepWithPendingException PASSED!"); 120 } 121 122 private int setCatchException() { 123 ReplyPacket replyPacket = debuggeeWrapper.vmMirror.setException( 124 getClassSignature(SingleStepWithPendingExceptionDebuggee.DebuggeeException.class), 125 true, true); 126 checkReplyPacket(replyPacket, "Failed to set EXCEPTION event request"); 127 return replyPacket.getNextValueAsInt(); 128 } 129 130 private int setSingleStepOut(long threadId) { 131 ReplyPacket replyPacket = debuggeeWrapper.vmMirror.setStep(new String[0], threadId, 132 JDWPConstants.StepSize.LINE, JDWPConstants.StepDepth.OUT); 133 checkReplyPacket(replyPacket, "Failed to set SINGLE_STEP OUT event request"); 134 return replyPacket.getNextValueAsInt(); 135 } 136 } 137