--- /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");
+ }
+ }
+}