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 Aleksander V. Budniy
21  */
22 
23 /**
24  * Created on 1.05.2006
25  */
26 package org.apache.harmony.jpda.tests.jdwp.StackFrame;
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.JDWPCommands;
31 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
32 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
33 import org.apache.harmony.jpda.tests.framework.jdwp.Value;
34 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
35 
36 /**
37  * JDWP Unit test for StackFrame.PopFrames command.
38  */
39 public class PopFrames002Test extends JDWPStackFrameTestCase {
40 
41     private String debuggeeSignature = "Lorg/apache/harmony/jpda/tests/jdwp/StackFrame/PopFramesDebuggee;";
42 
43     private String breakpointMethodName = "nestledMethod4";
44 
45     private String methodToPop = "nestledMethod2";
46 
47     private long timeoutToWait = 2000;
48 
49     private long timeOfMethodInvocation = timeoutToWait * 5;
50 
51     private static final byte NUMBER_OF_FRAMES_TO_POP = 3;
52 
getDebuggeeClassName()53     protected String getDebuggeeClassName() {
54         return PopFramesDebuggee.class.getName();
55     }
56 
57     /**
58      * This testcase exercises StackFrame.PopFrames command to discard several frames at once.
59      * <BR>The test starts PopFramesDebuggee class, sets a breakpoint
60      * in 'nestledMethod4', stops at breakpoint and prints stack.
61      * <BR>Then the test performs StackFrame.PopFrame command to discard several frames at once,
62      * prints stack and checks that discarded frames are not returned
63      * by ThreadReference.Frames command.
64      * <BR>Then the test resumes debuggee and checks stop on the same breakpoint.
65      */
testPopSeveralFrames()66     public void testPopSeveralFrames() {
67         logWriter.println("==> testPopSeveralFrames started");
68 
69         //check capability, relevant for this test
70         logWriter.println("=> Check capability: canPopFrames");
71         debuggeeWrapper.vmMirror.capabilities();
72         boolean isCapability = debuggeeWrapper.vmMirror.targetVMCapabilities.canPopFrames;
73         if (!isCapability) {
74             logWriter.println("##WARNING: this VM doesn't possess capability: canPopFrames");
75             return;
76         }
77 
78         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
79 
80         // find checked method
81         long refTypeID = getClassIDBySignature(debuggeeSignature);
82 
83         logWriter.println("=> Debuggee class = " + getDebuggeeClassName());
84 
85         // long methodID = getMethodID(refTypeID, breakpointMethodName);
86         logWriter.println("=> Set breakpoint at the beginning of " + breakpointMethodName);
87         int requestID = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(
88                 refTypeID, breakpointMethodName);
89 
90         // release debuggee
91         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
92 
93         // receive event in nestledMethod4
94         logWriter.println("=> Wait for breakpoint in " + breakpointMethodName);
95         long breakpointThreadID = debuggeeWrapper.vmMirror
96                 .waitForBreakpoint(requestID);
97 
98         logWriter.println("=> breakpointThreadID = " + breakpointThreadID);
99 
100         // print stack frames
101         logWriter.println("");
102         logWriter.println("=> Get frames before PopFrames command, thread = " + breakpointThreadID);
103         FrameInfo[] frameInfos = jdwpGetFrames(breakpointThreadID, 0, -1);
104         logWriter.println("=> Frames before popFrame");
105         printStackFrame(frameInfos.length, frameInfos);
106         logWriter.println("=> Number of frames before command: "
107                 + frameInfos.length);
108 
109         // find stack frame for popped method
110         logWriter.println("");
111         logWriter.println("=> Find frameID of method = " + methodToPop + " for PopFrames command");
112         long frameID = 0;
113         long methodID = getMethodID(refTypeID, methodToPop);
114         if (methodID == -1) {
115             logWriter.println("##FAILURE: error during getting methodID of " + methodToPop);
116         }
117         boolean isMethodFound = false;
118         for (int j = 0; j < frameInfos.length; j++) {
119             if (frameInfos[j].location.methodID == methodID) {
120                 frameID = frameInfos[j].getFrameID();
121                 isMethodFound = true;
122                 break;
123             }
124         }
125         if (!isMethodFound) {
126             logWriter
127                     .println("##FAILURE: there is no frame for checked method");
128             fail("There is no frame for checked method");
129         }
130 
131         logWriter.println("=> frameID for PopFrames command = " + frameID);
132 
133         // pop stack frames
134         logWriter.println("=> Pop " + NUMBER_OF_FRAMES_TO_POP + " frames at once");
135 
136         logWriter.println("");
137         logWriter.println("=> Perform PopFrames command for method = " + methodToPop + " with frameID = " + frameID);
138         jdwpPopFrames(breakpointThreadID, frameID);
139 
140         logWriter.println("=> Get frames after PopFrames command, thread = " + breakpointThreadID);
141         FrameInfo[] newFrameInfos = jdwpGetFrames(breakpointThreadID, 0, -1);
142 
143         logWriter.println("");
144         logWriter.println("=> Frames after popFrame");
145         logWriter.println("=> newNumberOfFrames = " + newFrameInfos.length);
146 
147         printStackFrame(newFrameInfos.length, newFrameInfos);
148         logWriter.println("=> Check that " + NUMBER_OF_FRAMES_TO_POP + " were discarded");
149         int numberOfPoppedFrames = frameInfos.length - newFrameInfos.length;
150         assertEquals("not all frames were discarded", numberOfPoppedFrames,
151                 NUMBER_OF_FRAMES_TO_POP);
152 
153         for (int i = numberOfPoppedFrames; i < (frameInfos.length); i++) {
154             if (frameInfos[i].location.methodID != newFrameInfos[i
155                     - numberOfPoppedFrames].location.methodID) {
156                 logWriter.println("## FAILURE: frames number " + i + " and "
157                         + (i - numberOfPoppedFrames) + " are not equal");
158                 fail("frames number are not equal");
159             }
160         }
161 
162         logWriter.println("=> Ckeck PASSED");
163         logWriter.println("=> Resume debuggee");
164         debuggeeWrapper.vmMirror.resume();
165 
166         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
167         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
168 
169         logWriter.println("=> Wait for breakpoint in " + breakpointMethodName);
170         breakpointThreadID = debuggeeWrapper.vmMirror
171                 .waitForBreakpoint(requestID);
172 
173         logWriter.println("=> Resume debuggee");
174         debuggeeWrapper.vmMirror.resume();
175 
176         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
177         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
178         logWriter.println("==> TEST popSeveralFrames PASSED");
179 
180     }
181 
182     /**
183      * This testcase exercises StackFrame.PopFrames command performing it several times.
184      * <BR>The test starts PopFramesDebuggee class, sets a breakpoint
185      * in 'nestledMethod4', stops at breakpoint and prints stack.
186      * <BR>Then the test performs StackFrame.PopFrame command several times
187      * to discard frames one after another,
188      * prints stack and checks that discarded frames are not returned
189      * by ThreadReference.Frames command.
190      * <BR>Then the test resumes debuggee and checks stop on the same breakpoint.
191      */
testPopSeveralTimes()192     public void testPopSeveralTimes() {
193         logWriter.println("==> testPopSeveralTimes started");
194 
195         //check capability, relevant for this test
196         logWriter.println("=> Check capability: canPopFrames");
197         debuggeeWrapper.vmMirror.capabilities();
198         boolean isCapability = debuggeeWrapper.vmMirror.targetVMCapabilities.canPopFrames;
199         if (!isCapability) {
200             logWriter.println("##WARNING: this VM doesn't possess capability: canPopFrames");
201             return;
202         }
203         // pass nestledMethod1()
204         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
205 
206         // find checked method
207         long refTypeID = getClassIDBySignature(debuggeeSignature);
208 
209         logWriter.println("=> Debuggee class = " + getDebuggeeClassName());
210 
211         logWriter.println("=> Set breakpoint at the beginning of " + breakpointMethodName);
212         int requestID = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(
213                 refTypeID, breakpointMethodName);
214 
215         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
216 
217         // receive event
218         logWriter.println("=> Wait for breakpoint in " + breakpointMethodName);
219         long breakpointThreadID = debuggeeWrapper.vmMirror
220                 .waitForBreakpoint(requestID);
221 
222         logWriter.println("=> breakpointThreadID = " + breakpointThreadID);
223 
224         // print stack frames
225         logWriter.println("");
226         logWriter.println("=> Get frames before PopFrames command, thread = " + breakpointThreadID);
227         FrameInfo[] frameInfos = jdwpGetFrames(breakpointThreadID, 0, -1);
228         logWriter.println("=> Frames before popFrame");
229         printStackFrame(frameInfos.length, frameInfos);
230         int framesBeforePop = frameInfos.length;
231         logWriter
232                 .println("=> Number of frames before command: " + framesBeforePop);
233 
234         logWriter.println("");
235         logWriter.println("=> Pop " + NUMBER_OF_FRAMES_TO_POP
236                 + " frames one after another");
237         logWriter.println("");
238         for (int i = 0; i < 3; i++) {
239             logWriter.println("=> Pop frame#" + i);
240             frameInfos = jdwpGetFrames(breakpointThreadID, 0, -1);
241             logWriter.println("=> Perform PopFrames command with frameID = " + frameInfos[0].getFrameID());
242             jdwpPopFrames(breakpointThreadID, frameInfos[0].getFrameID());
243         }
244 
245         logWriter.println("=> Get frames after PopFrames command, thread = " + breakpointThreadID);
246         FrameInfo[] newFrameInfos = jdwpGetFrames(breakpointThreadID, 0, -1);
247 
248         logWriter.println("");
249         logWriter.println("=> Frames after popFrame");
250         logWriter.println("=> newNumberOfFrames = " + newFrameInfos.length);
251 
252         printStackFrame(newFrameInfos.length, newFrameInfos);
253 
254         logWriter.println("=> Check that " + NUMBER_OF_FRAMES_TO_POP + " frames were discarded");
255         int numberOfPoppedFrames = framesBeforePop - newFrameInfos.length;
256         assertEquals("not all frames were discarded", numberOfPoppedFrames,
257                 NUMBER_OF_FRAMES_TO_POP);
258 
259         logWriter.println("=> Resume debuggee");
260         debuggeeWrapper.vmMirror.resume();
261 
262         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
263         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
264 
265         logWriter.println("=> Wait for breakpoint in " + breakpointMethodName);
266         breakpointThreadID = debuggeeWrapper.vmMirror
267                 .waitForBreakpoint(requestID);
268 
269         logWriter.println("=> Resume debuggee");
270         debuggeeWrapper.vmMirror.resume();
271 
272         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
273         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
274 
275         logWriter.println("==> TEST popSeveralTimes PASSED");
276     }
277 
278     /**
279      * This testcase exercises StackFrame.PopFrames command when thread is not suspended.
280      * <BR>The test starts PopFramesDebuggee class, sets a breakpoint
281      * in 'nestledMethod4', stops at breakpoint and prints stack.
282      * <BR>Then the test performs ClassType.InvokeMethodCommand without waiting reply, and
283      * waits to ensure that method was started.
284      * <BR>During working of method the test performs StackFrame.PopFrames command.
285      * Then the test checks that StackFrame.PopFrames command
286      * returns error: THREAD_NOT_SUSPENDED or INVALID_FRAMEID.
287      * <BR>Next, the test receives reply from invoked method and resumes debuggee..
288      */
testPopFramesWithInvokeMethods()289     public void testPopFramesWithInvokeMethods() {
290         logWriter.println("==> testPopFramesWithInvokeMethods started");
291 
292         //check capability, relevant for this test
293         logWriter.println("=> Check capability: canPopFrames");
294         debuggeeWrapper.vmMirror.capabilities();
295         boolean isCapability = debuggeeWrapper.vmMirror.targetVMCapabilities.canPopFrames;
296         if (!isCapability) {
297             logWriter.println("##WARNING: this VM doesn't possess capability: canPopFrames");
298             return;
299         }
300         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
301 
302         // find checked method
303         long refTypeID = getClassIDBySignature(debuggeeSignature);
304 
305         logWriter.println("=> Debuggee class = " + getDebuggeeClassName());
306 
307         logWriter.println("=> Set breakpoint at the beginning of " + breakpointMethodName);
308         int requestID = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(
309                 refTypeID, breakpointMethodName);
310 
311         // release debuggee
312         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
313 
314         // receive event
315         logWriter.println("=> Wait for breakpoint in " + breakpointMethodName);
316         long breakpointThreadID = debuggeeWrapper.vmMirror
317                 .waitForBreakpoint(requestID);
318 
319         logWriter.println("=> breakpointThreadID = " + breakpointThreadID);
320 
321         // print stack frames
322         logWriter.println("");
323         logWriter.println("=> Get frames before PopFrames command, thread = " + breakpointThreadID);
324         FrameInfo[] frameInfos = jdwpGetFrames(breakpointThreadID, 0, -1);
325         printStackFrame(frameInfos.length, frameInfos);
326         logWriter.println("=> Number of frames before command: "
327                 + frameInfos.length);
328 
329         // find frameID to pop
330         logWriter.println("");
331         logWriter.println("=> Find frameID of method = " + methodToPop + " for PopFrames command");
332         long frameID = 0;
333         long methodID = getMethodID(refTypeID, methodToPop);
334         boolean isMethodFound = false;
335         for (int j = 0; j < frameInfos.length; j++) {
336             if (frameInfos[j].location.methodID == methodID) {
337                 frameID = frameInfos[j].getFrameID();
338                 isMethodFound = true;
339                 break;
340             }
341         }
342         if (!isMethodFound) {
343             logWriter
344                     .println("##FAILURE: there is no frame for checked method");
345             fail("There is no frame for checked method");
346         }
347 
348         logWriter.println("=> frameID for PopFrames command = " + frameID);
349 
350         // create JDWP command for MethodInvoke with a long running method
351         long debuggeeRefTypeID = debuggeeWrapper.vmMirror
352                 .getClassID(debuggeeSignature);
353         logWriter.println("=> Find toInvokeMethodID for method: " + PopFramesDebuggee.METHOD_TO_INVOKE_NAME);
354         long toInvokeMethodID = debuggeeWrapper.vmMirror.getMethodID(
355                 debuggeeRefTypeID, PopFramesDebuggee.METHOD_TO_INVOKE_NAME);
356         if (toInvokeMethodID == -1) {
357             logWriter
358                     .println("## FAILURE: Can NOT get toInvokeMethodID for method: "
359                             + PopFramesDebuggee.METHOD_TO_INVOKE_NAME);
360             fail("## Can NOT get toInvokeMethodID");
361         }
362         logWriter.println("=> toInvokeMethodID = " + toInvokeMethodID);
363 
364         int invokeCommandID = 0;
365         CommandPacket invokeCommand = new CommandPacket(
366                 JDWPCommands.ClassTypeCommandSet.CommandSetID,
367                 JDWPCommands.ClassTypeCommandSet.InvokeMethodCommand);
368         invokeCommand.setNextValueAsClassID(debuggeeRefTypeID);
369         invokeCommand.setNextValueAsThreadID(breakpointThreadID);
370         invokeCommand.setNextValueAsMethodID(toInvokeMethodID);
371         invokeCommand.setNextValueAsInt(1); // args number
372         invokeCommand.setNextValueAsValue(new Value(timeOfMethodInvocation));
373         invokeCommand
374                 .setNextValueAsInt(JDWPConstants.InvokeOptions.INVOKE_SINGLE_THREADED);
375 
376         // send MethodInvoke command, but not wait for reply
377         try {
378             logWriter
379                     .println("=> Send InvokeMethod command for method: " + PopFramesDebuggee.METHOD_TO_INVOKE_NAME);
380             invokeCommandID = debuggeeWrapper.vmMirror
381                     .sendCommand(invokeCommand);
382         } catch (Exception e) {
383             logWriter.println("Exception during invokeCommand: " + e);
384             throw new TestErrorException(e);
385         }
386 
387         // wait to ensure that method invocation started
388         logWriter.println("=> Wait " + timeoutToWait
389                 + " mls to ensure that method invocation started");
390         Object waitObj = new Object();
391         synchronized (waitObj) {
392             try {
393                 waitObj.wait(timeoutToWait);
394             } catch (InterruptedException e) {
395                 logWriter.println("##Exception while waiting on object: " + e);
396                 throw new TestErrorException(e);
397             }
398         }
399 
400         // perform PopFrame command
401         logWriter.println("=> Perform PopFrames command for method = " + methodToPop + " with frameID = " + frameID + " and expect errors");
402         CommandPacket popFramesCommand = new CommandPacket(
403                 JDWPCommands.StackFrameCommandSet.CommandSetID,
404                 JDWPCommands.StackFrameCommandSet.PopFramesCommand);
405         popFramesCommand.setNextValueAsThreadID(breakpointThreadID);
406         popFramesCommand.setNextValueAsFrameID(frameID);
407 
408         ReplyPacket popFrameReply = debuggeeWrapper.vmMirror
409                 .performCommand(popFramesCommand);
410         int res = popFrameReply.getErrorCode();
411         logWriter.println("=> Returned error code: " + res + " ("
412                 + JDWPConstants.Error.getName(res) + ")");
413 
414         // check that PopFrames returns error, because thread is resumed by
415         // InvokeMethod
416         if (res == JDWPConstants.Error.NONE) {
417             logWriter
418                     .println("##PopFrames command returned no error for thread resumed by InvokeMethod");
419             fail("##PopFrames command returned no error for thread resumed by InvokeMethod");
420         }
421 
422         logWriter.println("=> Receive reply of invoked method: " + PopFramesDebuggee.METHOD_TO_INVOKE_NAME);
423         try {
424             ReplyPacket reply = debuggeeWrapper.vmMirror
425                     .receiveReply(invokeCommandID);
426             checkReplyPacket(reply, "ClassType::InvokeMethod command");
427         } catch (Exception e) {
428             logWriter
429                     .println("##Exception while receiving reply for invoke command: "
430                             + e);
431             throw new TestErrorException(e);
432         }
433 
434         logWriter.println("=> Resume debuggee");
435         debuggeeWrapper.vmMirror.resume();
436 
437         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
438         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
439         logWriter.println("==> TEST testPopFramesWithInvokeMethods PASSED");
440     }
441 
printStackFrame(int NumberOfFrames, FrameInfo[] frameInfos)442     void printStackFrame(int NumberOfFrames, FrameInfo[] frameInfos) {
443         for (int i = 0; i < NumberOfFrames; i++) {
444             logWriter.println(" ");
445             logWriter
446                     .println("=> #" + i + " frameID=" + frameInfos[i].frameID);
447             String methodName = getMethodName(frameInfos[i].location.classID,
448                     frameInfos[i].location.methodID);
449             logWriter.println("=> method name=" + methodName);
450         }
451         logWriter.println("");
452     }
453 }
454