8193150: Create a jtreg version of the test from JDK-8187143.
authorpsomashe
Fri, 09 Feb 2018 09:56:05 -0800
changeset 48952 e999964446d7
parent 48951 950c35ea6237
child 48953 67aa88701d46
8193150: Create a jtreg version of the test from JDK-8187143. Summary: Create a new jtreg test based on the test attached to the bug and add it to the ProblemsList. Reviewed-by: sspitsyn, cjplummer
test/jdk/ProblemList.txt
test/jdk/com/sun/jdi/NashornPopFrameTest.java
--- a/test/jdk/ProblemList.txt	Fri Feb 09 08:23:42 2018 -0500
+++ b/test/jdk/ProblemList.txt	Fri Feb 09 09:56:05 2018 -0800
@@ -481,6 +481,8 @@
 
 com/sun/jdi/sde/SourceDebugExtensionTest.java                   8158066 windows-all
 
+com/sun/jdi/NashornPopFrameTest.java                            8187143 generic-all
+
 ############################################################################
 
 # jdk_time
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/NashornPopFrameTest.java	Fri Feb 09 09:56:05 2018 -0800
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2001, 2018, 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 8187143
+ * @summary JDI crash in ~BufferBlob::MethodHandles adapters
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g NashornPopFrameTest.java
+ * @run driver NashornPopFrameTest
+ */
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import javax.script.*;
+
+import java.io.PrintStream;
+
+
+// The debuggee, creates and uses a Nashorn engine to evaluate a simple script.
+
+// The debugger  tries to set a breakpoint in Nashorn internal DEBUGGER method.
+// When the breakpoint is reached, it looks for stack frame whose method's
+// declaring type name starts with jdk.nashorn.internal.scripts.Script$.
+// (nashorn dynamically generated classes)
+// It then pops stack frames using the ThreadReference.popFrames() call, up to
+// and including the above stackframe.
+// The execution of the debuggee application is resumed after the needed
+// frames have been popped.
+
+class ScriptDebuggee {
+    public final static int BKPT_LINE = 74;
+    static ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+    static public String failReason = null;
+
+    static void doit() throws Exception {
+        System.out.println("Debugee: started!");
+        String script =
+                "function f() {\r\n" +
+                        " debugger;\r\n" +
+                        " debugger;\r\n" +
+                        "}\r\n" +
+                        "f();";
+        try {
+            engine.eval(script);
+        } catch (Exception ex) {
+            failReason = "ScriptDebuggee failed: Exception in engine.eval(): "
+                    + ex.toString();
+            ex.printStackTrace();
+        }
+        System.out.println("Debugee: finished!"); // BKPT_LINE
+    }
+
+    public static void main(String[] args) throws Exception {
+        doit();
+    }
+}
+
+/********** test program **********/
+
+public class NashornPopFrameTest extends TestScaffold {
+    static PrintStream out = System.out;
+    static boolean breakpointReached = false;
+    String debuggeeFailReason = null;
+    ClassType targetClass;
+    ThreadReference mainThread;
+    BreakpointRequest bkptRequest;
+
+    NashornPopFrameTest(String args[]) {
+        super(args);
+    }
+
+    public static void main(String[] args)      throws Exception {
+        NashornPopFrameTest nashornPopFrameTest = new NashornPopFrameTest(args);
+        nashornPopFrameTest.startTests();
+    }
+
+    /********** test core **********/
+
+    protected void runTests() throws Exception {
+        /*
+         * Get to the top of main() to determine targetClass and mainThread
+         */
+        BreakpointEvent bpe = startToMain("ScriptDebuggee");
+        targetClass = (ClassType)bpe.location().declaringType();
+        out.println("Agent: runTests: after startToMain()");
+
+        mainThread = bpe.thread();
+        EventRequestManager erm = vm().eventRequestManager();
+
+        Location loc = findLocation(targetClass, ScriptDebuggee.BKPT_LINE);
+
+        try {
+            addListener(this);
+        } catch (Exception ex){
+            ex.printStackTrace();
+            failure("Failed: Could not add listener");
+            throw new Exception("NashornPopFrameTest: failed with Exception in AddListener");
+        }
+
+        pauseAtDebugger(vm());
+        bkptRequest = erm.createBreakpointRequest(loc);
+        bkptRequest.enable();
+
+        vm().resume();
+
+        try {
+            listen(vm());
+        } catch (Exception exp) {
+            exp.printStackTrace();
+            failure("Failed: Caught Exception while Listening");
+            throw new Exception("NashornPopFrameTest: failed with Exception in listen()");
+        }
+
+        // Debugger continues to run until it receives a VMdisconnect event either because
+        // the Debuggee crashed / got exception / finished successfully.
+        while (!vmDisconnected) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException ee) {
+            }
+        }
+
+        removeListener(this);
+
+        if (breakpointReached) {
+            if (debuggeeFailReason != null) {
+                failure(debuggeeFailReason);
+            }
+        } else {
+            failure("Expected breakpoint in ScriptDebuggee:" +
+                    ScriptDebuggee.BKPT_LINE + " was not reached");
+        }
+        if (testFailed) {
+            throw new Exception("NashornPopFrameTest: failed");
+        }
+        out.println("NashornPopFrameTest: passed");
+    }
+
+    private static void pauseAtDebugger(VirtualMachine vm) throws AbsentInformationException {
+        for (ReferenceType t : vm.allClasses()) pauseAtDebugger(t);
+    }
+
+    // Set a breakpoint in Nashorn internal DEBUGGER method.
+    private static void pauseAtDebugger(ReferenceType t) throws AbsentInformationException {
+        if (!t.name().endsWith(".ScriptRuntime")) {
+            return;
+        }
+        for (Location l : t.allLineLocations()) {
+            if (!l.method().name().equals("DEBUGGER")) continue;
+            BreakpointRequest bkptReq = t.virtualMachine().eventRequestManager().createBreakpointRequest(l);
+            out.println("Setting breakpoint for " + l);
+            bkptReq.enable();
+            break;
+        }
+    }
+
+    private static void listen(VirtualMachine vm) throws Exception {
+        EventQueue eventQueue = vm.eventQueue();
+        EventSet es = eventQueue.remove();
+        if (es != null) {
+            handle(es);
+        }
+    }
+
+    // Handle event when breakpoint is reached
+    private static void handle(EventSet eventSet) throws Exception {
+        out.println("Agent handle(): started");
+        for (Event event : eventSet) {
+            if (event instanceof BreakpointEvent) {
+                findFrameAndPop(event);
+            }
+        }
+        eventSet.resume();
+        out.println("Agent handle(): finished");
+    }
+
+    private static void findFrameAndPop(Event event) throws Exception {
+        ThreadReference thread = ((BreakpointEvent) event).thread();
+        out.println("Agent: handling Breakpoint " + " at " +
+                ((BreakpointEvent) event).location() +
+                " in thread: " + thread);
+        StackFrame sf = findScriptFrame(thread);
+        if (sf != null) {
+            out.println("Thread Pop Frame on StackFrame = " + sf);
+            thread.popFrames(sf);
+        }
+    }
+
+    // Find stack frame whose method's declaring type name starts with
+    // jdk.nashorn.internal.scripts.Script$ and return that frame
+    private static StackFrame findScriptFrame(ThreadReference t) throws IncompatibleThreadStateException {
+        for (int i = 0; i < t.frameCount(); i++) {
+            StackFrame sf = t.frame(i);
+            String typeName = sf.location().method().declaringType().name();
+            if (typeName.startsWith("jdk.nashorn.internal.scripts.Script$")) {
+                out.println("Agent: in findScriptFrame: TypeName = " + typeName);
+                return sf;
+            }
+        }
+        throw new RuntimeException("no script frame");
+    }
+
+    static int bkptCount = 0;
+
+    /********** event handlers **********/
+
+    public void breakpointReached(BreakpointEvent event) {
+        ThreadReference thread = ((BreakpointEvent) event).thread();
+        String locStr = "" + ((BreakpointEvent) event).location();
+        out.println("Agent: BreakpointEvent #" + (bkptCount++) +
+                " at " + locStr + " in thread: " + thread);
+        if (locStr.equals("ScriptDebuggee:" + ScriptDebuggee.BKPT_LINE)) {
+            breakpointReached = true;
+            Field failReasonField = targetClass.fieldByName("failReason");
+            Value failReasonVal = targetClass.getValue(failReasonField);
+            if (failReasonVal != null) {
+                debuggeeFailReason = ((StringReference)failReasonVal).value();
+            }
+            bkptRequest.disable();
+        }
+    }
+
+    public void eventSetComplete(EventSet set) {
+        set.resume();
+    }
+
+    public void vmDisconnected(VMDisconnectEvent event) {
+        println("Agent: Got VMDisconnectEvent");
+    }
+
+}