test/jdk/com/sun/jdi/redefine/RedefineTest.java
changeset 47216 71c04702a3d5
parent 44423 306c020eb154
child 51987 c4010f88ea68
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/redefine/RedefineTest.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2001, 2015, 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 4287595
+ * @bug 4462989
+ * @bug 4531511
+ * @summary Test class redefinition
+ *
+ * @author Robert Field
+ *
+ * @library ..
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g RedefineTest.java
+ * @run shell RedefineSetUp.sh
+ * @run driver RedefineTest
+ */
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import java.util.*;
+import java.io.*;
+
+    /********** target program **********/
+
+class RedefineTarg {
+    public static void show(String where){
+        System.out.println("Returned: " + where);
+    }
+
+    public static void lastly(String where){
+    }
+
+    public static void main(String[] args){
+        RedefineSubTarg sub = new RedefineSubTarg();
+        String where = "";
+        for (int i = 0; i < 5; ++i) {
+            where = sub.foo(where);
+            show(where);
+        }
+        lastly(where);
+    }
+}
+
+    /********** test program **********/
+
+public class RedefineTest extends TestScaffold {
+    ReferenceType targetClass;
+    static final String expected ="Boring Boring Different Boring Different ";
+    int repetitionCount = 0;
+    boolean beforeRedefine = true;
+
+    RedefineTest (String args[]) {
+        super(args);
+    }
+
+    public static void main(String[] args)      throws Exception {
+        new RedefineTest(args).startTests();
+    }
+
+    /********** event handlers **********/
+
+    public void methodEntered(MethodEntryEvent event) {
+        Method meth = event.location().method();
+        ThreadReference thread = event.thread();
+
+        if (meth.name().equals("foo")) {
+            ++repetitionCount;
+            beforeRedefine = true;
+            try {
+                expectNonObsolete(thread);
+                inspectLineNumber(event, thread.frame(0));
+
+                doRedefine(thread);
+                beforeRedefine = false;
+
+                switch (repetitionCount) {
+                case 1:
+                case 5:
+                    expectNonObsolete(thread);
+                    inspectLineNumber(event, thread.frame(0));
+                    break;
+                case 2:
+                case 3:
+                case 4:
+                    expectObsolete(thread);
+                    inspectLineNumber(event, thread.frame(0));
+                    break;
+                }
+
+
+            } catch (Exception exc) {
+                failure("Test Failure: unexpected exception - " + exc);
+                exc.printStackTrace();
+            }
+        }
+    }
+
+    public void breakpointReached(BreakpointEvent event) {
+        ThreadReference thread = event.thread();
+        try {
+            StackFrame frame = thread.frame(0);
+            LocalVariable lv = frame.visibleVariableByName("where");
+            Value vWhere = frame.getValue(lv);
+            String remoteWhere = ((StringReference)vWhere).value();
+            println("Value of where: " + remoteWhere);
+            if (!remoteWhere.equals(expected)) {
+                failure("FAIL: expected result string: '" + expected +
+                        "' got: '" + remoteWhere + "'");
+            }
+        } catch (Exception thr) {
+            failure("Test Failure: unexpected exception: " + thr);
+        }
+    }
+
+    /********** test assists **********/
+
+    void expectNonObsolete(ThreadReference thread) throws Exception {
+        if (isObsolete(thread)) {
+            failure("FAIL: Method should NOT be obsolete");
+        } else {
+            println("as it should be, not obsolete");
+        }
+    }
+
+    void expectObsolete(ThreadReference thread) throws Exception {
+        if (isObsolete(thread)) {
+            println("obsolete like it should be");
+        } else {
+            failure("FAIL: Method should be obsolete");
+        }
+    }
+
+    void inspectLineNumber(LocatableEvent event, StackFrame frame) throws Exception {
+        /*
+         * For each value of repetitionCount, use the beforeRedefine
+         * boolean to distinguish the time before and after the actual
+         * redefinition takes place.  Line numbers are inspected both
+         * before and after each redefine.
+         */
+        int n = -1;
+        int expectedLine = -1;
+        switch (repetitionCount) {
+        case 1:
+            expectedLine = 4;
+            break;
+        case 2:
+            expectedLine = beforeRedefine ? 4:21;
+            break;
+        case 3:
+            expectedLine = beforeRedefine ? 21:4;
+            break;
+        case 4:
+            expectedLine = beforeRedefine ? 4:21;
+            break;
+        case 5:
+            /* The class won't be redefined on this iteration (look
+             * for a java.lang.UnsupportedOperationException instead)
+             * so expected line stays the same as last successful
+             * redefine.
+             */
+            expectedLine = 21;
+            break;
+        }
+        Method method = event.location().method();
+        if (frame.location().method().isObsolete()) {
+            /*
+             * Then skip. Obsolete methods are not interesting to
+             * inspect.
+             */
+            println("inspectLineNumber skipping obsolete method " + method.name());
+        } else {
+            n = method.location().lineNumber();
+            int m = frame.location().lineNumber();
+            if ((n != expectedLine) || (n != m)) {
+                failure("Test Failure: line number disagreement: " +
+                        n + " (event) versus " + m + " (frame) versus " + expectedLine +
+                        " (expected)");
+            } else {
+                println("inspectLineNumber in method " + method.name() + " at line " + n);
+            }
+        }
+    }
+
+    boolean isObsolete(ThreadReference thread) throws Exception {
+        StackFrame frame = thread.frame(0);
+        Method meth = frame.location().method();
+        return meth.isObsolete();
+    }
+
+    void doRedefine(ThreadReference thread) throws Exception {
+        Exception receivedException = null;
+        String fileName = "notThis";
+
+        switch (repetitionCount) {
+        case 1:
+            fileName = "RedefineSubTarg.class";
+            break;
+        case 2:
+            fileName = "Different_RedefineSubTarg.class";
+            break;
+        case 3:
+            fileName = "RedefineSubTarg.class";
+            break;
+        case 4:
+            fileName = "Different_RedefineSubTarg.class";
+            break;
+        case 5:
+            fileName = "SchemaChange_RedefineSubTarg.class";
+            break;
+        }
+        File phyl = new File(fileName);
+        byte[] bytes = new byte[(int)phyl.length()];
+        InputStream in = new FileInputStream(phyl);
+        in.read(bytes);
+        in.close();
+
+        Map map = new HashMap();
+        map.put(findReferenceType("RedefineSubTarg"), bytes);
+
+        println(System.getProperty("line.separator") + "Iteration # " + repetitionCount +
+                " ------ Redefine as: " + fileName);
+        try {
+            vm().redefineClasses(map);
+        } catch (Exception thr) {
+            receivedException = thr;
+        }
+        switch (repetitionCount) {
+        case 5:
+            if (receivedException == null) {
+                failure("FAIL: no exception; expected: UnsupportedOperationException");
+            } else if (receivedException instanceof UnsupportedOperationException) {
+                println("Received expected exception: " + receivedException);
+            } else {
+                failure("FAIL: got exception: " + receivedException +
+                        ", expected: UnsupportedOperationException");
+            }
+            break;
+        default:
+            if (receivedException != null) {
+                failure("FAIL: unexpected exception: " +
+                        receivedException);
+            }
+            break;
+        }
+        return;
+    }
+
+    /********** test core **********/
+
+    protected void runTests() throws Exception {
+
+        BreakpointEvent bpe = startToMain("RedefineTarg");
+        targetClass = bpe.location().declaringType();
+        EventRequestManager erm = vm().eventRequestManager();
+
+        /*
+         * Method entry in sub targ
+         */
+        MethodEntryRequest mee = erm.createMethodEntryRequest();
+        mee.addClassFilter("RedefineSubTarg");
+        mee.enable();
+
+        /*
+         * BP at end to get value
+         */
+        List lastlys = targetClass.methodsByName("lastly");
+        if (lastlys.size() != 1) {
+            throw new Exception ("TestFailure: Expected one 'lastly' method, found: " +
+                                 lastlys);
+        }
+        Location loc = ((Method)(lastlys.get(0))).location();
+        EventRequest req = erm.createBreakpointRequest(loc);
+        req.enable();
+
+        // Allow application to complete and shut down
+        listenUntilVMDisconnect();
+
+        /*
+         * deal with results of test
+         * if anything has called failure("foo") testFailed will be true
+         */
+        if (!testFailed) {
+            println("RedefineTest: passed");
+        } else {
+            throw new Exception("RedefineTest: failed");
+        }
+    }
+}