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 Vitaly A. Provodin
21  */
22 
23 /**
24  * Created on 15.02.2005
25  */
26 package org.apache.harmony.jpda.tests.jdwp.ThreadReference;
27 
28 import java.util.Vector;
29 import java.util.Enumeration;
30 
31 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
32 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
33 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
34 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
35 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
36 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
37 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
38 
39 /**
40  * JDWP Unit test for ThreadReference.Frames command.
41  */
42 public class FramesTest extends JDWPSyncTestCase {
43 
44     short err;
45     long threadID;
46 
47     class FrameStruct {
48         long frameID;
49         Location loc;
FrameStruct(long frameID, Location loc)50         FrameStruct(long frameID, Location loc) {
51             this.frameID = frameID;
52             this.loc = loc;
53         }
54     }
55 
getDebuggeeClassName()56     protected String getDebuggeeClassName() {
57         return "org.apache.harmony.jpda.tests.jdwp.ThreadReference.FramesDebuggee";
58     }
59 
60     /**
61      * This testcase exercises ThreadReference.Frames command.
62      * <BR>At first the test starts FramesDebuggee which recursively invokes
63      * the method 'FramesDebuggee.recursiveMethod' thereby the specified depth
64      * 'FramesDebuggee.DEPTH' of recursion is reached.
65      * <BR> Then the tests performs the ThreadReference.Frames command
66      * for the main thread with parameters:
67      * <BR>startFrame=0, length=(amount_of_all_frames + 1)
68      * <BR>It is expected the error INVALID_LENGTH is returned.
69      */
testFrames005()70     public void testFrames005() {
71         logWriter.println("==> testFrames005 START ");
72         String testedThreadName = synchronizer.receiveMessage();
73 
74         logWriter.println
75         ("==> testedThreadName = |" + testedThreadName +"|");
76         threadID = debuggeeWrapper.vmMirror.getThreadID(testedThreadName);
77         logWriter.println("==> threadID = " + threadID);
78         debuggeeWrapper.vmMirror.suspendThread(threadID);
79 
80         Vector allFrames = getFrames(0, -1);
81         if (err != JDWPConstants.Error.NONE) {
82             printErrorAndFail("Unexpected ERROR = " + err
83                     + "(" + JDWPConstants.Error.getName(err) + ")");
84         }
85         String methodName, classSignature;
86         int i = 0;
87         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
88             FrameStruct frame = (FrameStruct )e.nextElement();
89             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
90             classSignature = getClassSignature(frame.loc.classID);
91             logWriter.println("\t" + i + ". frameID=" + frame.frameID
92                     + " - " + classSignature
93                     + methodName
94                     + "(" + frame.loc.index + ")");
95         }
96 
97         allFrames = getFrames(0, allFrames.size() + 1);
98         if (err == JDWPConstants.Error.INVALID_LENGTH) {
99             logWriter.println("Caught expected error - " + JDWPConstants.Error.getName(err)
100                     + "(" + err + ")");
101         } else {
102             printErrorAndFail("unexpected behaviour: error is "
103                     + JDWPConstants.Error.getName(err) + "(" + err + ")"
104                     + " but  must be "
105                     + JDWPConstants.Error.getName(JDWPConstants.Error.INVALID_LENGTH)
106                     + "(" + JDWPConstants.Error.INVALID_LENGTH + ")");
107         }
108         logWriter.println("==> testFrames005 OK. ");
109         debuggeeWrapper.vmMirror.resumeThread(threadID);
110 
111         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
112     }
113 
114     /**
115      * This testcase exercises ThreadReference.Frames command.
116      * <BR>At first the test starts FramesDebuggee which recursively invokes
117      * the method 'FramesDebuggee.recursiveMethod' thereby the specified depth
118      * 'FramesDebuggee.DEPTH' of recursion is reached.
119      * <BR> Then the tests performs the ThreadReference.Frames command
120      * for the main thread with parameters:
121      * <BR>startFrame=(amount_of_all_frames + 1), length=-1
122      * <BR>It is expected the error INVALID_INDEX is returned.
123      */
testFrames004()124     public void testFrames004() {
125         logWriter.println("==> testFrames004 START ");
126         String testedThreadName = synchronizer.receiveMessage();
127 
128         logWriter.println
129         ("==> testedThreadName = |" + testedThreadName +"|");
130         threadID = debuggeeWrapper.vmMirror.getThreadID(testedThreadName);
131         logWriter.println("==> threadID = " + threadID);
132         debuggeeWrapper.vmMirror.suspendThread(threadID);
133 
134         Vector allFrames = getFrames(0, -1);
135         if (err != JDWPConstants.Error.NONE) {
136             printErrorAndFail("Unexpected ERROR = " + err
137                     + "(" + JDWPConstants.Error.getName(err) + ")");
138         }
139         String methodName, classSignature;
140         int i = 0;
141         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
142             FrameStruct frame = (FrameStruct )e.nextElement();
143             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
144             classSignature = getClassSignature(frame.loc.classID);
145             logWriter.println("\t" + i + ". frameID=" + frame.frameID
146                        + " - " + classSignature
147                     + methodName
148                     + "(" + frame.loc.index + ")");
149         }
150 
151         allFrames = getFrames(allFrames.size() + 1, -1);
152         if (err == JDWPConstants.Error.INVALID_INDEX) {
153             logWriter.println("Caught expected error - " + JDWPConstants.Error.getName(err)
154                     + "(" + err + ")");
155         } else {
156             printErrorAndFail("unexpected behaviour: error is "
157                     + JDWPConstants.Error.getName(err) + "(" + err + ")"
158                     + " but  must be "
159                     + JDWPConstants.Error.getName(JDWPConstants.Error.INVALID_INDEX)
160                     + "(" + JDWPConstants.Error.INVALID_INDEX + ")");
161         }
162 
163         logWriter.println("==> testFrames004 OK. ");
164         debuggeeWrapper.vmMirror.resumeThread(threadID);
165 
166         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
167     }
168 
169     /**
170      * This testcase exercises ThreadReference.Frames command.
171      * <BR>At first the test starts FramesDebuggee which recursively invokes
172      * the method 'FramesDebuggee.recursiveMethod' thereby the specified depth
173      * 'FramesDebuggee.DEPTH' of recursion is reached.
174      * <BR> Then the tests performs the ThreadReference.Frames command
175      * for the main thread with parameters:
176      * <BR>startFrame=amount_of_all_frames, length=-1
177      * <BR>It is expected an empty set of frames is returned.
178      */
testFrames003()179     public void testFrames003() {
180         logWriter.println("==> testFrames003 START ");
181         String testedThreadName = synchronizer.receiveMessage();
182 
183         logWriter.println
184         ("==> testedThreadName = |" + testedThreadName +"|");
185         threadID = debuggeeWrapper.vmMirror.getThreadID(testedThreadName);
186         logWriter.println("==> threadID = " + threadID);
187         debuggeeWrapper.vmMirror.suspendThread(threadID);
188 
189         Vector allFrames = getFrames(0, -1);
190         if (err != JDWPConstants.Error.NONE) {
191             printErrorAndFail("Unexpected ERROR = " + err
192                     + "(" + JDWPConstants.Error.getName(err) + ")");
193         }
194         String methodName, classSignature;
195         int i = 0;
196         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
197             FrameStruct frame = (FrameStruct )e.nextElement();
198             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
199             classSignature = getClassSignature(frame.loc.classID);
200                logWriter.println("\t" + i + ". frameID=" + frame.frameID
201                        + " - " + classSignature
202                     + methodName
203                     + "(" + frame.loc.index + ")");
204         }
205 
206         allFrames = getFrames(allFrames.size(), -1);
207         if (err != JDWPConstants.Error.NONE) {
208             printErrorAndFail("Unexpected ERROR = " + err
209                     + "(" + JDWPConstants.Error.getName(err) + ")");
210         }
211         if (allFrames.size() == 0) {
212             logWriter.println("empty set of frames is returned");
213         } else {
214             printErrorAndFail("it is expected an empty set of frames, but frameCount = "
215                     + allFrames.size());
216         }
217 
218         logWriter.println("==> testFrames003 OK. ");
219         debuggeeWrapper.vmMirror.resumeThread(threadID);
220 
221         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
222     }
223 
224     /**
225      * This testcase exercises ThreadReference.Frames command.
226      * <BR>At first the test starts FramesDebuggee which recursively invokes
227      * the method 'FramesDebuggee.recursiveMethod' thereby the specified depth
228      * 'FramesDebuggee.DEPTH' of recursion is reached.
229      * <BR>Then the test by ThreadReference.Frames command
230      * requests all frames and looks for the first frame
231      * which has location in the 'recursiveMethod'.
232      * <BR>The index of such frame is passed as startFrame parameter for
233      * the second invocation of ThreadReference.Frames command.
234      * <BR>The length (the second parameter) is set to 'FramesDebuggee.DEPTH'.
235      * <BR>It is expected that the amount of returned frames is equal to
236      * 'FramesDebuggee.DEPTH' and all returned frames have locations in
237      * 'recursiveMethod'.
238      */
testFrames002()239     public void testFrames002() {
240         logWriter.println("==> testFrames002 START ");
241         String testedThreadName = synchronizer.receiveMessage();
242 
243         logWriter.println
244         ("==> testedThreadName = |" + testedThreadName +"|");
245         threadID = debuggeeWrapper.vmMirror.getThreadID(testedThreadName);
246         logWriter.println("==> threadID = " + threadID);
247         debuggeeWrapper.vmMirror.suspendThread(threadID);
248 
249         Vector allFrames = getFrames(0, -1);
250         if (err != JDWPConstants.Error.NONE) {
251             printErrorAndFail("Unexpected ERROR = " + err
252                     + "(" + JDWPConstants.Error.getName(err) + ")");
253         }
254         String methodName, classSignature;
255         int frameNumber = -1;
256         int i = 0;
257         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
258             FrameStruct frame = (FrameStruct )e.nextElement();
259             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
260             classSignature = getClassSignature(frame.loc.classID);
261             if (frameNumber < 0 && FramesDebuggee.METHOD_NAME.equals(methodName)) {
262                 frameNumber = i;
263             }
264                logWriter.println("\t" + i + ". frameID=" + frame.frameID
265                        + " - " + classSignature
266                     + methodName
267                     + "(" + frame.loc.index + ")");
268         }
269 
270         if (frameNumber < 0) {
271             printErrorAndFail("frameNumber is unexpectedly equal to " + frameNumber);
272         }
273 
274         allFrames = getFrames(frameNumber, FramesDebuggee.DEPTH);
275         if (err != JDWPConstants.Error.NONE) {
276             printErrorAndFail("Unexpected ERROR = " + err
277                     + "(" + JDWPConstants.Error.getName(err) + ")");
278         }
279         i = frameNumber;
280         int methodCount = 0;
281         String unexpectedMethods = null;
282         String depthError = null;
283         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
284             FrameStruct frame = (FrameStruct )e.nextElement();
285             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
286             classSignature = getClassSignature(frame.loc.classID);
287             logWriter.println("\t" + i + ". frameID=" + frame.frameID
288                     + " - " + classSignature
289                     + methodName
290                     + "(" + frame.loc.index + ")");
291 
292                if (methodName.equals(FramesDebuggee.METHOD_NAME)) {
293                    methodCount++;
294                } else {
295                    logWriter.printError("unexpected method - " + methodName);
296                    unexpectedMethods = null == unexpectedMethods ? methodName : unexpectedMethods + "," + methodName;
297                }
298         }
299 
300         if (methodCount != FramesDebuggee.DEPTH) {
301             logWriter.printError(depthError = ("Number of " + FramesDebuggee.METHOD_NAME + " in frames "
302                     + methodCount + "  but expected " + FramesDebuggee.DEPTH));
303         }
304 
305         debuggeeWrapper.vmMirror.resumeThread(threadID);
306         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
307 
308         if (null != unexpectedMethods) {
309             logWriter.println("==> testFrames002 FAILED ");
310             fail("unexpected method(s): " + unexpectedMethods);
311         }
312         else if (null != depthError) {
313             logWriter.println("==> testFrames002 FAILED ");
314             fail(depthError);
315         } else {
316             logWriter.println("==> testFrames002 OK. ");
317         }
318     }
319 
320     /**
321      * This testcase exercises ThreadReference.Frames command.
322      * <BR>At first the test starts FramesDebuggee which recursively invokes
323      * the method 'FramesDebuggee.recursiveMethod' thereby the specified depth
324      * 'FramesDebuggee.DEPTH' of recursion is reached.
325      * <BR>Then the test by ThreadReference.Frames command
326      * requests all frames and looks for the first frame
327      * which has location in the 'recursiveMethod'.
328      * <BR>The index of such frame is passed as startFrame parameter for
329      * the second invocation of ThreadReference.Frames command.
330      * <BR>The length (the second parameter) is set to '-1'.
331      * <BR>It is expected that the amount of returned frames which are located in
332      * 'recursiveMethod' is equal to 'FramesDebuggee.DEPTH'.
333      */
testFrames001()334     public void testFrames001() {
335         logWriter.println("==> testFrames001 START ");
336         String testedThreadName = synchronizer.receiveMessage();
337 
338         logWriter.println
339         ("==> testedThreadName = |" + testedThreadName +"|");
340         threadID = debuggeeWrapper.vmMirror.getThreadID(testedThreadName);
341         logWriter.println("==> threadID = " + threadID);
342         debuggeeWrapper.vmMirror.suspendThread(threadID);
343 
344         Vector allFrames = getFrames(0, -1);
345         if (err != JDWPConstants.Error.NONE) {
346             printErrorAndFail("Unexpected ERROR = " + err
347                     + "(" + JDWPConstants.Error.getName(err) + ")");
348         }
349         String methodName, classSignature;
350         int frameNumber = -1;
351         int i = 0;
352         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
353             FrameStruct frame = (FrameStruct )e.nextElement();
354             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
355             classSignature = getClassSignature(frame.loc.classID);
356             if (frameNumber < 0 && FramesDebuggee.METHOD_NAME.equals(methodName)) {
357                 frameNumber = i;
358             }
359             logWriter.println("\t" + i + ". frameID=" + frame.frameID
360                     + " - " + classSignature
361                     + methodName
362                     + "(" + frame.loc.index + ")");
363         }
364 
365         if (frameNumber < 0) {
366             logWriter.printError("frameNumber is unexpectedly equal to " + frameNumber);
367             assertTrue("Invalid frameNumber", frameNumber > 0);
368         }
369 
370         allFrames = getFrames(frameNumber, -1);
371         if (err != JDWPConstants.Error.NONE) {
372             printErrorAndFail("Unexpected ERROR = " + err
373                     + "(" + JDWPConstants.Error.getName(err) + ")");
374         }
375         i = frameNumber;
376         int methodCount = 0;
377         boolean testCondition;
378         String unexpectedMethods = null;
379         String depthError = null;
380         for (Enumeration e = allFrames.elements(); e.hasMoreElements(); i++) {
381             FrameStruct frame = (FrameStruct )e.nextElement();
382             methodName = getMethodName(frame.loc.classID, frame.loc.methodID);
383             classSignature = getClassSignature(frame.loc.classID);
384             logWriter.println("\t" + i + ". frameID=" + frame.frameID
385                     + " - " + classSignature
386                     + methodName
387                     + "(" + frame.loc.index + ")");
388                testCondition = (i == frameNumber
389                        && !methodName.equals(FramesDebuggee.METHOD_NAME));
390                if (testCondition) {
391                    logWriter.printError("unexpected method name of the first frame - "
392                            + methodName);
393                    unexpectedMethods = null == unexpectedMethods ? methodName : unexpectedMethods + "," + methodName;
394                }
395 
396                if (methodName.equals(FramesDebuggee.METHOD_NAME)) {
397                    methodCount++;
398                }
399         }
400 
401         if (methodCount != FramesDebuggee.DEPTH) {
402             logWriter.printError(depthError = ("Number of " + FramesDebuggee.METHOD_NAME + " in frames "
403                     + methodCount + "  but expected " + FramesDebuggee.DEPTH));
404         }
405 
406         debuggeeWrapper.vmMirror.resumeThread(threadID);
407         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
408 
409         if (null != unexpectedMethods) {
410             logWriter.println("==> testFrames001 FAILED ");
411             fail("unexpected method(s): " + unexpectedMethods);
412         }
413         else if (null != depthError) {
414             logWriter.println("==> testFrames001 FAILED ");
415             fail(depthError);
416         } else {
417             logWriter.println("==> testFrames001 OK. ");
418         }
419     }
420 
getFrames(int startFrame, int length)421     private Vector getFrames(int startFrame, int length) {
422 
423         Vector<FrameStruct> frames = new Vector<FrameStruct>();
424 
425         logWriter.println("startFrame=" + startFrame
426                 + "; length=" + length);
427 
428         // getting frames of the thread
429         CommandPacket packet = new CommandPacket(
430                 JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
431                 JDWPCommands.ThreadReferenceCommandSet.FramesCommand);
432         packet.setNextValueAsThreadID(threadID);
433         packet.setNextValueAsInt(startFrame);
434         packet.setNextValueAsInt(length);
435         ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
436         err = reply.getErrorCode();
437         if ( err != JDWPConstants.Error.NONE) {
438             logWriter.println("\tthreadID=" + threadID
439                     + " - " + JDWPConstants.Error.getName(err));
440             return null;
441         }
442         int framesCount = reply.getNextValueAsInt();
443         long frameID;
444         Location loc;
445         logWriter.println("framesCount=" + framesCount);
446         for (int j = 0; j < framesCount; j++) {
447                frameID = reply.getNextValueAsFrameID();
448                loc = reply.getNextValueAsLocation();
449                frames.add(new FrameStruct(frameID, loc));
450            }
451         return frames;
452     }
453 }
454