1 /* 2 * Copyright (c) 2001, 2002, 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 4467564 27 * @summary Test the popping of frames in an asynchronous context 28 * (that is, when suspended by the debugger at random points) 29 * 30 * @author Robert Field 31 * 32 * @run build TestScaffold VMConnection TargetListener TargetAdapter 33 * @run compile -g PopAsynchronousTest.java 34 * @run driver PopAsynchronousTest 35 */ 36 import com.sun.jdi.*; 37 import com.sun.jdi.event.*; 38 import com.sun.jdi.request.*; 39 40 import java.util.*; 41 42 /********** target program **********/ 43 44 class PopAsynchronousTarg { 45 static final int N = 30; 46 int fibonacci(int n) { 47 if (n <= 2) { 48 return 1; 49 } else { 50 return fibonacci(n-1) + fibonacci(n-2); 51 } 52 } 53 void report(int n, int result) { 54 System.out.println("fibonacci(" + n + ") = " + result); 55 } 56 public static void main(String[] args){ 57 int n = N; 58 System.out.println("Howdy!"); 59 PopAsynchronousTarg pat = new PopAsynchronousTarg(); 60 pat.report(n, pat.fibonacci(n)); 61 System.out.println("Goodbye from PopAsynchronousTarg!"); 62 } 63 } 64 65 /********** test program **********/ 66 67 public class PopAsynchronousTest extends TestScaffold { 68 ReferenceType targetClass; 69 ThreadReference mainThread; 70 int result = -1; 71 boolean harassTarget = true; 72 Object harassLock = new Object(); 73 74 PopAsynchronousTest (String args[]) { 75 super(args); 76 } 77 78 public static void main(String[] args) throws Exception { 79 new PopAsynchronousTest(args).startTests(); 80 } 81 82 83 84 /********** event handlers **********/ 85 86 87 public void breakpointReached(BreakpointEvent event) { 88 harassTarget = false; 89 synchronized(harassLock) { 90 try { 91 StackFrame frame = event.thread().frame(0); 92 LocalVariable lv = frame.visibleVariableByName("result"); 93 IntegerValue resultV = (IntegerValue)frame.getValue(lv); 94 result = resultV.value(); 95 } catch (Exception exc) { 96 exc.printStackTrace(System.err); 97 failure("TEST FAILURE: exception " + exc); 98 } 99 } 100 } 101 102 /********** test assist **********/ 103 104 105 class HarassThread extends Thread { 106 public void run() { 107 int harassCount = 0; 108 try { 109 int prev = 0; 110 int delayTime = 1; 111 112 synchronized(harassLock) { 113 while (harassTarget && (harassCount < 10)) { 114 boolean backoff = true; 115 mainThread.suspend(); 116 StackFrame top = mainThread.frame(0); 117 Method meth = top.location().method(); 118 String methName = meth.name(); 119 if (methName.equals("fibonacci")) { 120 LocalVariable lv = top.visibleVariableByName("n"); 121 IntegerValue nV = (IntegerValue)top.getValue(lv); 122 int n = nV.value(); 123 if (n != prev) { 124 backoff = false; 125 StackFrame popThis = top; 126 Iterator it = mainThread.frames().iterator(); 127 128 /* pop lowest fibonacci frame */ 129 while (it.hasNext()) { 130 StackFrame frame = (StackFrame)it.next(); 131 if (!frame.location().method().name().equals("fibonacci")) { 132 break; 133 } 134 popThis = frame; 135 } 136 println("popping fibonacci(" + n + ")"); 137 mainThread.popFrames(popThis); 138 ++harassCount; 139 prev = n; 140 } else { 141 println("ignoring another fibonacci(" + n + ")"); 142 } 143 } else { 144 println("ignoring " + methName); 145 } 146 if (backoff) { 147 delayTime *= 2; 148 } else { 149 delayTime /= 2; 150 if (delayTime < harassCount) { 151 delayTime = harassCount; 152 } 153 } 154 mainThread.resume(); 155 println("Delaying for " + delayTime + "ms"); 156 Thread.sleep(delayTime); 157 } 158 } 159 } catch (Exception exc) { 160 exc.printStackTrace(System.err); 161 failure("TEST FAILURE: exception " + exc); 162 } 163 println("Harassment complete, count = " + harassCount); 164 } 165 } 166 167 /********** test core **********/ 168 169 protected void runTests() throws Exception { 170 /* 171 * Get to the top of main() 172 * to determine targetClass and mainThread 173 */ 174 BreakpointEvent bpe = startToMain("PopAsynchronousTarg"); 175 targetClass = bpe.location().declaringType(); 176 mainThread = bpe.thread(); 177 EventRequestManager erm = vm().eventRequestManager(); 178 179 /* 180 * Set event requests 181 */ 182 List meths = targetClass.methodsByName("report"); 183 Location loc = ((Method)(meths.get(0))).location(); 184 BreakpointRequest request = erm.createBreakpointRequest(loc); 185 request.enable(); 186 187 /* 188 * start popping wildly away 189 */ 190 (new HarassThread()).start(); 191 192 /* 193 * resume the target listening for events 194 */ 195 listenUntilVMDisconnect(); 196 197 /* 198 * check result 199 */ 200 int correct = (new PopAsynchronousTarg()). 201 fibonacci(PopAsynchronousTarg.N); 202 if (result == correct) { 203 println("Got expected result: " + result); 204 } else { 205 failure("FAIL: expected result: " + correct + 206 ", got: " + result); 207 } 208 209 /* 210 * deal with results of test 211 * if anything has called failure("foo") testFailed will be true 212 */ 213 if (!testFailed) { 214 println("PopAsynchronousTest: passed"); 215 } else { 216 throw new Exception("PopAsynchronousTest: failed"); 217 } 218 } 219 }