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