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.CommandPacket; 22 import org.apache.harmony.jpda.tests.framework.jdwp.EventMod; 23 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 24 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 25 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.StepDepth; 26 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.StepSize; 27 import org.apache.harmony.jpda.tests.framework.jdwp.Location; 28 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent; 29 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.EventThreadLocation; 30 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 31 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 32 33 /** 34 * JDWP Unit test for SINGLE_STEP event. 35 */ 36 public class SingleStepThroughReflectionTest extends JDWPEventTestCase { 37 38 private static final String DEBUGGEE_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/Events/SingleStepThroughReflectionDebuggee;"; 39 40 private static final String DEBUGGEE_CLASS_NAME = "org.apache.harmony.jpda.tests.jdwp.Events.SingleStepThroughReflectionDebuggee"; 41 42 // The method where we set a breakpoint to suspend execution. 43 private static final String BREAKPOINT_METHOD = "breakpointTest"; 44 45 // The method where we expect to suspend with the single-step. 46 private static final String EVENT_METHOD = "methodCalledThroughReflection"; 47 getDebuggeeClassName()48 protected String getDebuggeeClassName() { 49 return DEBUGGEE_CLASS_NAME; 50 } 51 52 /** 53 * This test case exercises SINGLE_STEP INTO event through reflection.<BR> 54 * 55 * Runs SingleStepNativeDebuggee and sets breakpoint to its 56 * breakpointTest method, sends a request for single step event, then 57 * verifies that requested SINGLE_STEP event occurred in the 58 * methodCalledThroughReflection method. 59 * 60 */ testSingleStepIntoThroughReflection()61 public void testSingleStepIntoThroughReflection() { 62 logWriter.println("=> testSingleStepIntoThroughReflection started"); 63 64 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 65 66 // Find debuggee class id. 67 long refTypeID = getClassIDBySignature(DEBUGGEE_SIGNATURE); 68 logWriter.println("=> Debuggee class = " + getDebuggeeClassName()); 69 logWriter.println("=> referenceTypeID for Debuggee class = " + refTypeID); 70 logWriter.println("=> Send ReferenceType::Methods command and get methodIDs "); 71 72 // Set breakpoint to suspend execution. 73 int breakpointRequestID = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin( 74 refTypeID, BREAKPOINT_METHOD); 75 logWriter.println("=> breakpointID = " + breakpointRequestID); 76 logWriter.println("=> starting thread"); 77 78 // Resume debuggee so we hit the breakpoint. 79 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 80 81 // Wait for the breakpoint event. 82 long breakpointThreadID = debuggeeWrapper.vmMirror 83 .waitForBreakpoint(breakpointRequestID); 84 logWriter.println("=> breakpointThreadID = " + breakpointThreadID); 85 86 // Sending a SINGLE_STEP request with a ClassOnly modifier so we only 87 // suspend in the debuggee class. 88 CommandPacket setRequestCommand = new CommandPacket( 89 JDWPCommands.EventRequestCommandSet.CommandSetID, 90 JDWPCommands.EventRequestCommandSet.SetCommand); 91 setRequestCommand 92 .setNextValueAsByte(JDWPConstants.EventKind.SINGLE_STEP); 93 setRequestCommand.setNextValueAsByte(JDWPConstants.SuspendPolicy.ALL); 94 setRequestCommand.setNextValueAsInt(2); 95 setRequestCommand.setNextValueAsByte(EventMod.ModKind.Step); 96 setRequestCommand.setNextValueAsThreadID(breakpointThreadID); 97 setRequestCommand.setNextValueAsInt(StepSize.LINE); 98 setRequestCommand.setNextValueAsInt(StepDepth.INTO); 99 setRequestCommand.setNextValueAsByte(EventMod.ModKind.ClassOnly); 100 setRequestCommand.setNextValueAsReferenceTypeID(refTypeID); 101 102 ReplyPacket setRequestReply = debuggeeWrapper.vmMirror 103 .performCommand(setRequestCommand); 104 105 checkReplyPacket(setRequestReply, "Set SINGLE_STEP event"); 106 int stepRequestID = setRequestReply.getNextValueAsInt(); 107 108 logWriter.println("=> RequestID = " + stepRequestID); 109 assertAllDataRead(setRequestReply); 110 111 // Resume debuggee. 112 resumeDebuggee(); 113 114 ParsedEvent parsedEvent = waitForSingleStepEvent(stepRequestID); 115 116 // Clear SINGLE_STEP event. 117 clearSingleStep(stepRequestID); 118 119 // Check we stopped in the expected method. 120 checkSingleStepEvent((EventThreadLocation) parsedEvent, refTypeID); 121 122 logWriter.println("==> Resuming debuggee"); 123 resumeDebuggee(); 124 logWriter.println("==> Test PASSED!"); 125 } 126 checkSingleStepEvent(EventThreadLocation eventThreadLocation, long refTypeID)127 private void checkSingleStepEvent(EventThreadLocation eventThreadLocation, 128 long refTypeID) { 129 // Find expected method id. 130 long expectedMethodID = getMethodID(refTypeID, EVENT_METHOD); 131 132 // Dump where we stopped. 133 Location location = eventThreadLocation.getLocation(); 134 String className = getClassSignature(location.classID); 135 String methodName = getMethodName(location.classID, 136 location.methodID); 137 logWriter.println("Stopped in " + className + "." + methodName 138 + " at code index " + location.index); 139 140 // Check we stopped in the right method. 141 assertEquals("Stopped in wrong class", refTypeID, location.classID); 142 assertEquals("Stopped in wrong method", expectedMethodID, location.methodID); 143 } 144 waitForSingleStepEvent(int requestID)145 private ParsedEvent waitForSingleStepEvent(int requestID) { 146 logWriter.println("==> Wait for SINGLE_STEP event"); 147 CommandPacket event = debuggeeWrapper.vmMirror.receiveEvent(); 148 ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event); 149 150 logWriter.println("==> Received " + parsedEvents.length + " events"); 151 152 // Dump events. 153 for (int i = 0; i < parsedEvents.length; i++) { 154 logWriter.println(""); 155 logWriter.println("==> Event #" + i + ";"); 156 logWriter.println("==> EventKind: " + parsedEvents[i].getEventKind() + "(" 157 + JDWPConstants.EventKind.getName(parsedEvents[i].getEventKind()) + ")"); 158 logWriter.println("==> RequestID: " + parsedEvents[i].getRequestID()); 159 } 160 161 // We expect only one event. 162 assertEquals("Received wrong number of events,", 1, parsedEvents.length); 163 164 // Check this is the event we were waiting for. 165 ParsedEvent parsedEvent = parsedEvents[0]; 166 assertEquals("Received wrong event request ID,", requestID, parsedEvent.getRequestID()); 167 assertEquals("Invalid event kind,", JDWPConstants.EventKind.SINGLE_STEP, 168 parsedEvent.getEventKind(), 169 JDWPConstants.EventKind.getName(JDWPConstants.EventKind.SINGLE_STEP), 170 JDWPConstants.EventKind.getName(parsedEvent.getEventKind())); 171 172 return parsedEvent; 173 } 174 clearSingleStep(int stepRequestID)175 private void clearSingleStep(int stepRequestID) { 176 logWriter.println("==> Clearing SINGLE_STEP event.."); 177 ReplyPacket clearRequestReply = 178 debuggeeWrapper.vmMirror.clearEvent(JDWPConstants.EventKind.SINGLE_STEP, 179 stepRequestID); 180 checkReplyPacket(clearRequestReply, "Clear SINGLE_STEP event"); 181 logWriter.println("==> SINGLE_STEP event has been cleared"); 182 } 183 } 184