jdk/test/com/sun/jdi/PopAsynchronousTest.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/PopAsynchronousTest.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2001-2002 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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 main 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 extends Thread {
+        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
+         */
+        (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");
+        }
+    }
+}