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  *  @modules jdk.jdi
  30  *  @run build TestScaffold VMConnection TargetAdapter TargetListener
  31  *  @run compile -g MethodCalls.java
  32  *  @run compile -g MethodCallsReflection.java
  33  *  @run compile -g ControlFlow.java
  34  *  @run build StepTest
  35  *
  36  * @summary StepTest starts at a method named "go()" in the debuggee and
  37  * repetitively steps. It will do a step into until the maximum
  38  * stack depth (specified on command line) is reached. At that point
  39  * it begins to step over. Step granularity is determined from the
  40  * command line. Stepping is repeated the until the end of go() is reached
  41  * or until the requested number of steps (specified on command line)
  42  * is performed. An exception is thrown if the requested number of
  43  * steps does not result in the debuggee's location being at the end of
  44  * go().
  45  * This test is sensitive to the line number info generated by the compiler
  46  * for the debuggee files- MethodCalls.java, ...
  47  * See LineNumberInfo.java for more info.
  48  *
  49  *                     +--- maximum stack depth in debuggee
  50  *                     |  +--- step granularity: "line" or "min"
  51  *                     |  |    +---Expected number of steps
  52  *                     |  |    |  +--- Debuggee command Line
  53  *                     V  V    V  V      Workaround-----+
  54  *                                                      V
  55  *  @run driver StepTest 2 line  2 MethodCalls
  56  *  @run driver StepTest 3 line 14 MethodCalls
  57  *
  58  *  @run driver StepTest 2 line 18 MethodCallsReflection  12
  59  *
  60  *  @run driver StepTest 2 min   4 MethodCalls
  61  *  @run driver StepTest 3 min  43 MethodCalls
  62  *
  63  *  @run driver StepTest 2 line 65 ControlFlow            64
  64  */
  65 
  66 /*
  67  * The workaround column contains the expected number of steps
  68  * on non IA64 VMs.  These VMs get it wrong and should be
  69  * fixed (4787861).  When they are fixed, this test should be fixed
  70  * to remove this workaround.
  71  * The C interpreter in the IA64 VM handles catches differently
  72  * than the asm interpreter.  For the construct
  73  * line    statement
  74  * -----------------
  75  * 68      catch (Exception ee) {
  76  * 69          System.out.println(...)
  77  * javac outputs the store into ee as being on line 68 and the
  78  * start of the println on line 69.  The handler starts with the
  79  * store into ee, ie, line 68.  When a step is done under the
  80  * associated try and an exception is encountered,
  81  * the IA64 VM stops at line 68 while the other VM stops at
  82  * line 69.  It seems that the IA64 VM is correct.
  83  * But, it is too late to fix the other VM for Mantis,
  84  * so this test is being made so that it will pass both VMs.
  85  * For each catch that occurs, an extra step is needed
  86  * on the IA64 VM.  This only occurs in MethodCallsReflection
  87  * which contains 6 of these catches (so we have to do 6
  88  * extra steps to make it pass) and in ControlFlow which
  89  * does it once.
  90  *
  91  */
  92 import com.sun.jdi.*;
  93 import com.sun.jdi.event.*;
  94 import com.sun.jdi.request.*;
  95 
  96 import java.util.Map;
  97 import java.util.HashMap;
  98 
  99 public class StepTest extends TestScaffold {
 100     int maxDepth;
 101     String granularity;
 102     int expectedCount;
 103     int workaroundCount = 0;
 104     boolean lastStepNeeded = true;
 105     public static void main(String args[]) throws Exception {
 106         new StepTest(args).startTests();
 107     }
 108 
 109     StepTest(String args[]) throws Exception {
 110         super(args);
 111         maxDepth = Integer.decode(args[0]).intValue();
 112         granularity = args[1];
 113         expectedCount = Integer.decode(args[2]).intValue();
 114         if (args.length == 5) {
 115             workaroundCount = Integer.decode(args[4]).intValue();
 116         }
 117     }
 118 
 119     protected void runTests() throws Exception {
 120         // Skip test args
 121         String[] args2 = new String[args.length - 3];
 122         System.arraycopy(args, 3, args2, 0, args.length - 3);
 123 
 124         connect(args2);
 125         ThreadReference thread = waitForVMStart();
 126 
 127         StepEvent stepEvent = stepIntoLine(thread);
 128 
 129         String className = thread.frame(0).location().declaringType().name();
 130         System.out.println("\n\n-------Running test for class: " + className);
 131 
 132         BreakpointEvent bpEvent = resumeTo(className, "go", "()V");
 133         thread = bpEvent.thread();
 134 
 135         for (int i = 0; i < expectedCount; i++) {
 136             if (thread.frameCount() < maxDepth) {
 137                 if (granularity.equals("line")) {
 138                     stepEvent = stepIntoLine(thread);
 139                 } else {
 140                     stepEvent = stepIntoInstruction(thread);
 141                 }
 142             } else {
 143                 if (granularity.equals("line")) {
 144                     stepEvent = stepOverLine(thread);
 145                 } else {
 146                     stepEvent = stepOverInstruction(thread);
 147                 }
 148             }
 149             System.out.println("Step #" + (i+1) + "complete at " +
 150                                stepEvent.location().method().name() + ":" +
 151                                stepEvent.location().lineNumber() + " (" +
 152                                stepEvent.location().codeIndex() + "), frameCount = " +
 153                                thread.frameCount());
 154             if (thread.frameCount() < 2) {
 155                 // We have stepped one step too far.  If we did exactly
 156                 // the 'workaround' number of steps, then this is in all
 157                 // likelihood the non IA64 VM.  So, stop.
 158                 if (i == workaroundCount) {
 159                     lastStepNeeded = false;
 160                     break;
 161                 }
 162                 // Gone too far, past return of go()
 163                 throw new Exception("Stepped too far");
 164             }
 165         }
 166 
 167         if (thread.frameCount() > 2) {
 168             // Not far enough
 169             throw new Exception("Didn't step far enough (" + thread.frame(0) + ")");
 170         }
 171 
 172         if (lastStepNeeded) {
 173             // One last step takes us out of go()
 174             stepIntoLine(thread);
 175         }
 176         if (thread.frameCount() != 1) {
 177             // Gone too far
 178             throw new Exception("Didn't step far enough (" + thread.frame(0) + ")");
 179         }
 180 
 181         // Allow application to complete
 182         resumeToVMDisconnect();
 183 
 184         if (!testFailed) {
 185             println("StepTest: passed");
 186         } else {
 187             throw new Exception("StepTest: failed");
 188         }
 189     }
 190 }