ee9776fa23
Reviewed-by: amenkov, cjplummer
219 lines
7.5 KiB
Java
219 lines
7.5 KiB
Java
/*
|
|
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/**
|
|
* @test
|
|
* @bug 4467564
|
|
* @summary Test the popping of frames in an asynchronous context
|
|
* (that is, when suspended by the debugger at random points)
|
|
* @author Robert Field
|
|
*
|
|
* @run build TestScaffold VMConnection TargetListener TargetAdapter
|
|
* @run compile -g PopAsynchronousTest.java
|
|
* @run driver PopAsynchronousTest
|
|
*/
|
|
import com.sun.jdi.*;
|
|
import com.sun.jdi.event.*;
|
|
import com.sun.jdi.request.*;
|
|
|
|
import java.util.*;
|
|
|
|
/********** target program **********/
|
|
|
|
class PopAsynchronousTarg {
|
|
static final int N = 30;
|
|
int fibonacci(int n) {
|
|
if (n <= 2) {
|
|
return 1;
|
|
} else {
|
|
return fibonacci(n-1) + fibonacci(n-2);
|
|
}
|
|
}
|
|
void report(int n, int result) {
|
|
System.out.println("fibonacci(" + n + ") = " + result);
|
|
}
|
|
public static void main(String[] args){
|
|
int n = N;
|
|
System.out.println("Howdy!");
|
|
PopAsynchronousTarg pat = new PopAsynchronousTarg();
|
|
pat.report(n, pat.fibonacci(n));
|
|
System.out.println("Goodbye from PopAsynchronousTarg!");
|
|
}
|
|
}
|
|
|
|
/********** test program **********/
|
|
|
|
public class PopAsynchronousTest extends TestScaffold {
|
|
ReferenceType targetClass;
|
|
ThreadReference mainThread;
|
|
int result = -1;
|
|
boolean harassTarget = true;
|
|
Object harassLock = new Object();
|
|
|
|
PopAsynchronousTest (String args[]) {
|
|
super(args);
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
new PopAsynchronousTest(args).startTests();
|
|
}
|
|
|
|
|
|
|
|
/********** event handlers **********/
|
|
|
|
|
|
public void breakpointReached(BreakpointEvent event) {
|
|
harassTarget = false;
|
|
synchronized(harassLock) {
|
|
try {
|
|
StackFrame frame = event.thread().frame(0);
|
|
LocalVariable lv = frame.visibleVariableByName("result");
|
|
IntegerValue resultV = (IntegerValue)frame.getValue(lv);
|
|
result = resultV.value();
|
|
} catch (Exception exc) {
|
|
exc.printStackTrace(System.err);
|
|
failure("TEST FAILURE: exception " + exc);
|
|
}
|
|
}
|
|
}
|
|
|
|
/********** test assist **********/
|
|
|
|
|
|
class HarassThread implements Runnable {
|
|
public void run() {
|
|
int harassCount = 0;
|
|
try {
|
|
int prev = 0;
|
|
int delayTime = 1;
|
|
|
|
synchronized(harassLock) {
|
|
while (harassTarget && (harassCount < 10)) {
|
|
boolean backoff = true;
|
|
mainThread.suspend();
|
|
StackFrame top = mainThread.frame(0);
|
|
Method meth = top.location().method();
|
|
String methName = meth.name();
|
|
if (methName.equals("fibonacci")) {
|
|
LocalVariable lv = top.visibleVariableByName("n");
|
|
IntegerValue nV = (IntegerValue)top.getValue(lv);
|
|
int n = nV.value();
|
|
if (n != prev) {
|
|
backoff = false;
|
|
StackFrame popThis = top;
|
|
Iterator it = mainThread.frames().iterator();
|
|
|
|
/* pop lowest fibonacci frame */
|
|
while (it.hasNext()) {
|
|
StackFrame frame = (StackFrame)it.next();
|
|
if (!frame.location().method().name().equals("fibonacci")) {
|
|
break;
|
|
}
|
|
popThis = frame;
|
|
}
|
|
println("popping fibonacci(" + n + ")");
|
|
mainThread.popFrames(popThis);
|
|
++harassCount;
|
|
prev = n;
|
|
} else {
|
|
println("ignoring another fibonacci(" + n + ")");
|
|
}
|
|
} else {
|
|
println("ignoring " + methName);
|
|
}
|
|
if (backoff) {
|
|
delayTime *= 2;
|
|
} else {
|
|
delayTime /= 2;
|
|
if (delayTime < harassCount) {
|
|
delayTime = harassCount;
|
|
}
|
|
}
|
|
mainThread.resume();
|
|
println("Delaying for " + delayTime + "ms");
|
|
Thread.sleep(delayTime);
|
|
}
|
|
}
|
|
} catch (Exception exc) {
|
|
exc.printStackTrace(System.err);
|
|
failure("TEST FAILURE: exception " + exc);
|
|
}
|
|
println("Harassment complete, count = " + harassCount);
|
|
}
|
|
}
|
|
|
|
/********** test core **********/
|
|
|
|
protected void runTests() throws Exception {
|
|
/*
|
|
* Get to the top of main()
|
|
* to determine targetClass and mainThread
|
|
*/
|
|
BreakpointEvent bpe = startToMain("PopAsynchronousTarg");
|
|
targetClass = bpe.location().declaringType();
|
|
mainThread = bpe.thread();
|
|
EventRequestManager erm = vm().eventRequestManager();
|
|
|
|
/*
|
|
* Set event requests
|
|
*/
|
|
List meths = targetClass.methodsByName("report");
|
|
Location loc = ((Method)(meths.get(0))).location();
|
|
BreakpointRequest request = erm.createBreakpointRequest(loc);
|
|
request.enable();
|
|
|
|
/*
|
|
* start popping wildly away
|
|
*/
|
|
DebuggeeWrapper.newThread(new HarassThread()).start();
|
|
|
|
/*
|
|
* resume the target listening for events
|
|
*/
|
|
listenUntilVMDisconnect();
|
|
|
|
/*
|
|
* check result
|
|
*/
|
|
int correct = (new PopAsynchronousTarg()).
|
|
fibonacci(PopAsynchronousTarg.N);
|
|
if (result == correct) {
|
|
println("Got expected result: " + result);
|
|
} else {
|
|
failure("FAIL: expected result: " + correct +
|
|
", got: " + result);
|
|
}
|
|
|
|
/*
|
|
* deal with results of test
|
|
* if anything has called failure("foo") testFailed will be true
|
|
*/
|
|
if (!testFailed) {
|
|
println("PopAsynchronousTest: passed");
|
|
} else {
|
|
throw new Exception("PopAsynchronousTest: failed");
|
|
}
|
|
}
|
|
}
|