1 /*
   2  * Copyright (c) 1999, 2004, 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;
 104     public static void main(String args[]) throws Exception {
 105         new StepTest(args).startTests();
 106     }
 107 
 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 
 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 }