1 /*
2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /**
25  * @test
26  * @bug 4270488 4787861
27  * @author Gordon Hirsch
28  *
29  * @run build TestScaffold VMConnection TargetAdapter TargetListener
30  * @run compile -g MethodCalls.java
31  * @run compile -g MethodCallsReflection.java
32  * @run compile -g ControlFlow.java
33  * @run build StepTest
34  *
35  * @summary StepTest starts at a method named "go()" in the debuggee and
36  * repetitively steps. It will do a step into until the maximum
37  * stack depth (specified on command line) is reached. At that point
38  * it begins to step over. Step granularity is determined from the
39  * command line. Stepping is repeated the until the end of go() is reached
40  * or until the requested number of steps (specified on command line)
41  * is performed. An exception is thrown if the requested number of
42  * steps does not result in the debuggee's location being at the end of
43  * go().
44  * This test is sensitive to the line number info generated by the compiler
45  * for the debuggee files- MethodCalls.java, ...
46  * See LineNumberInfo.java for more info.
47  *
48  *                      +--- maximum stack depth in debuggee
49  *                      |  +--- step granularity: "line" or "min"
50  *                      |  |    +---Expected number of steps
51  *                      |  |    |  +--- Debuggee command Line
52  *                      V  V    V  V      Workaround-----+
53  *                                                       V
54  * @run driver StepTest 2 line  2 MethodCalls
55  * @run driver StepTest 3 line 14 MethodCalls
56  *
57  * @run driver StepTest 2 line 18 MethodCallsReflection  12
58  *
59  * @run driver StepTest 2 min   4 MethodCalls
60  * @run driver StepTest 3 min  43 MethodCalls
61  *
62  * @run driver StepTest 2 line 65 ControlFlow            64
63  */
64 
65 /*
66  * The workaround column contains the expected number of steps
67  * on non IA64 VMs.  These VMs get it wrong and should be
68  * fixed (4787861).  When they are fixed, this test should be fixed
69  * to remove this workaround.
70  * The C interpreter in the IA64 VM handles catches differently
71  * than the asm interpreter.  For the construct
72  * line    statement
73  * -----------------
74  * 68      catch (Exception ee) {
75  * 69          System.out.println(...)
76  * javac outputs the store into ee as being on line 68 and the
77  * start of the println on line 69.  The handler starts with the
78  * store into ee, ie, line 68.  When a step is done under the
79  * associated try and an exception is encountered,
80  * the IA64 VM stops at line 68 while the other VM stops at
81  * line 69.  It seems that the IA64 VM is correct.
82  * But, it is too late to fix the other VM for Mantis,
83  * so this test is being made so that it will pass both VMs.
84  * For each catch that occurs, an extra step is needed
85  * on the IA64 VM.  This only occurs in MethodCallsReflection
86  * which contains 6 of these catches (so we have to do 6
87  * extra steps to make it pass) and in ControlFlow which
88  * does it once.
89  *
90  */
91 import com.sun.jdi.*;
92 import com.sun.jdi.event.*;
93 import com.sun.jdi.request.*;
94 
95 import java.util.Map;
96 import java.util.HashMap;
97 
98 public class StepTest extends TestScaffold {
99     int maxDepth;
100     String granularity;
101     int expectedCount;
102     int workaroundCount = 0;
103     boolean lastStepNeeded = true;
main(String args[])104     public static void main(String args[]) throws Exception {
105         new StepTest(args).startTests();
106     }
107 
StepTest(String args[])108     StepTest(String args[]) throws Exception {
109         super(args);
110         maxDepth = Integer.decode(args[0]).intValue();
111         granularity = args[1];
112         expectedCount = Integer.decode(args[2]).intValue();
113         if (args.length == 5) {
114             workaroundCount = Integer.decode(args[4]).intValue();
115         }
116     }
117 
runTests()118     protected void runTests() throws Exception {
119         // Skip test args
120         String[] args2 = new String[args.length - 3];
121         System.arraycopy(args, 3, args2, 0, args.length - 3);
122 
123         connect(args2);
124         ThreadReference thread = waitForVMStart();
125 
126         StepEvent stepEvent = stepIntoLine(thread);
127 
128         String className = thread.frame(0).location().declaringType().name();
129         System.out.println("\n\n-------Running test for class: " + className);
130 
131         BreakpointEvent bpEvent = resumeTo(className, "go", "()V");
132         thread = bpEvent.thread();
133 
134         for (int i = 0; i < expectedCount; i++) {
135             if (thread.frameCount() < maxDepth) {
136                 if (granularity.equals("line")) {
137                     stepEvent = stepIntoLine(thread);
138                 } else {
139                     stepEvent = stepIntoInstruction(thread);
140                 }
141             } else {
142                 if (granularity.equals("line")) {
143                     stepEvent = stepOverLine(thread);
144                 } else {
145                     stepEvent = stepOverInstruction(thread);
146                 }
147             }
148             System.out.println("Step #" + (i+1) + "complete at " +
149                                stepEvent.location().method().name() + ":" +
150                                stepEvent.location().lineNumber() + " (" +
151                                stepEvent.location().codeIndex() + "), frameCount = " +
152                                thread.frameCount());
153             if (thread.frameCount() < 2) {
154                 // We have stepped one step too far.  If we did exactly
155                 // the 'workaround' number of steps, then this is in all
156                 // likelihood the non IA64 VM.  So, stop.
157                 if (i == workaroundCount) {
158                     lastStepNeeded = false;
159                     break;
160                 }
161                 // Gone too far, past return of go()
162                 throw new Exception("Stepped too far");
163             }
164         }
165 
166         if (thread.frameCount() > 2) {
167             // Not far enough
168             throw new Exception("Didn't step far enough (" + thread.frame(0) + ")");
169         }
170 
171         if (lastStepNeeded) {
172             // One last step takes us out of go()
173             stepIntoLine(thread);
174         }
175         if (thread.frameCount() != 1) {
176             // Gone too far
177             throw new Exception("Didn't step far enough (" + thread.frame(0) + ")");
178         }
179 
180         // Allow application to complete
181         resumeToVMDisconnect();
182 
183         if (!testFailed) {
184             println("StepTest: passed");
185         } else {
186             throw new Exception("StepTest: failed");
187         }
188     }
189 }
190