Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001.java
41161 views
/*1* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package nsk.jdi.BScenarios.hotswap;2425import nsk.share.*;26import nsk.share.jpda.*;27import nsk.share.jdi.*;2829import com.sun.jdi.*;30import com.sun.jdi.request.*;31import com.sun.jdi.event.*;3233import java.util.*;34import java.io.*;3536/**37* This test is from the group of so-called Borland's scenarios and38* implements the following test case:39* Suite 3 - Hot Swap40* Test case: TC241* Description: Before point of execution, same method42* Steps: 1.Set breakpoint at line 24 (call to b()43* from a())44* 2.Debug Main45* 3.Insert as line before point of46* execution: System.err.println("foo");47* 4.Smart Swap48* 5.Set Smart PopFrame to beginging of49* method a()50* 6.Resume51* X. Prints out "foo" and hits breakpoint52* on line 2453* 7.Resume54* X. Prints numbers55* The description was drown up according to steps under JBuilder.56*57* Of course, the test has own line numbers and method/class names and58* works as follow:59* When the test is starting debugee, debugger sets breakpoint at60* the 38th line (method <code>method_A</code>).61* After the breakpoint is reached, debugger: <br>62* - redefines debugee adding a new line into "method_A", <br>63* - pops current frame <br>64* and resumes debugee.65* It is expected the new code will be actual after the redefining and66* it doesn't hit breakpoint according to JVMDI Redefine Classes spec :67* "...All breakpoints in the class are cleared."68*/6970public class tc02x001 {7172public final static String UNEXPECTED_STRING = "***Unexpected exception ";7374private final static String prefix = "nsk.jdi.BScenarios.hotswap.";75private final static String debuggerName = prefix + "tc02x001";76private final static String debugeeName = debuggerName + "a";7778private final static String newClassFile = "newclass" + File.separator79+ debugeeName.replace('.',File.separatorChar)80+ ".class";8182private static int exitStatus;83private static Log log;84private static Debugee debugee;85private static long waitTime;86private static String classDir;8788private int expectedEventCount = 5;89private int eventCount = 0;9091private ReferenceType debugeeClass;9293private static void display(String msg) {94log.display(msg);95}9697private static void complain(String msg) {98log.complain("debugger FAILURE> " + msg + "\n");99}100101public static void main(String argv[]) {102System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out));103}104105public static int run(String argv[], PrintStream out) {106107exitStatus = Consts.TEST_PASSED;108109tc02x001 thisTest = new tc02x001();110111ArgumentHandler argHandler = new ArgumentHandler(argv);112log = new Log(out, argHandler);113114classDir = argv[0];115waitTime = argHandler.getWaitTime() * 60000;116117Binder binder = new Binder(argHandler, log);118debugee = binder.bindToDebugee(debugeeName);119120try {121thisTest.execTest();122} catch (Throwable e) {123exitStatus = Consts.TEST_FAILED;124e.printStackTrace();125} finally {126debugee.endDebugee();127}128display("Test finished. exitStatus = " + exitStatus);129130return exitStatus;131}132133private void execTest() throws Failure {134135if (!debugee.VM().canRedefineClasses()) {136display("\n>>>canRedefineClasses() is false<<< test canceled.\n");137return;138}139140display("\nTEST BEGINS");141display("===========");142143EventSet eventSet = null;144EventIterator eventIterator = null;145Event event;146long totalTime = waitTime;147long tmp, begin = System.currentTimeMillis(),148delta = 0;149boolean exit = false;150151EventRequestManager evm = debugee.getEventRequestManager();152ClassPrepareRequest req = evm.createClassPrepareRequest();153req.addClassFilter(debugeeName);154req.enable();155debugee.resume();156157while (totalTime > 0 && !exit) {158if (eventIterator == null || !eventIterator.hasNext()) {159try {160eventSet = debugee.VM().eventQueue().remove(totalTime);161} catch (InterruptedException e) {162new Failure(e);163}164if (eventSet != null) {165eventIterator = eventSet.eventIterator();166} else {167eventIterator = null;168}169}170if (eventIterator != null) {171while (eventIterator.hasNext()) {172event = eventIterator.nextEvent();173// display("\n event ===>>> " + event);174175if (event instanceof ClassPrepareEvent) {176display("\n event ===>>> " + event);177debugeeClass = ((ClassPrepareEvent )event).referenceType();178display("Tested class\t:" + debugeeClass.name());179debugee.setBreakpoint(debugeeClass,180tc02x001a.brkpMethodName,181tc02x001a.brkpLineNumber);182183debugee.resume();184eventCount++;185186} else if (event instanceof BreakpointEvent) {187display("\n event ===>>> " + event);188switch (eventCount) {189case 1:190display("redefining...");191redefineDebugee();192popFrames(((BreakpointEvent )event).thread());193createMethodExitRequest(debugeeClass);194195break;196197default:198complain("Unexpected breakpoint event");199exitStatus = Consts.TEST_FAILED;200}201eventCount++;202hitBreakpoint((BreakpointEvent )event);203debugee.resume();204205} else if (event instanceof MethodExitEvent) {206display("\n event ===>>> " + event);207hitMethodExit((MethodExitEvent)event);208eventCount++;209debugee.resume();210211} else if (event instanceof VMDeathEvent) {212exit = true;213break;214} else if (event instanceof VMDisconnectEvent) {215exit = true;216break;217} // if218} // while219} // if220tmp = System.currentTimeMillis();221delta = tmp - begin;222totalTime -= delta;223begin = tmp;224}225226if (eventCount != expectedEventCount) {227if (totalTime <= 0) {228complain("out of wait time...");229}230complain("expecting " + expectedEventCount231+ " events, but "232+ eventCount + " events arrived.");233exitStatus = Consts.TEST_FAILED;234}235236display("=============");237display("TEST FINISHES\n");238}239240private void redefineDebugee() {241Map<? extends com.sun.jdi.ReferenceType,byte[]> mapBytes;242boolean alreadyComplained = false;243mapBytes = mapClassToBytes(newClassFile);244try {245debugee.VM().redefineClasses(mapBytes);246} catch (Exception e) {247throw new Failure(UNEXPECTED_STRING + e);248}249}250251private void popFrames(ThreadReference thread) {252try {253StackFrame frame = thread.frame(0);254thread.popFrames(frame);255} catch (IncompatibleThreadStateException e) {256throw new Failure(UNEXPECTED_STRING + e);257}258}259260private Map<? extends com.sun.jdi.ReferenceType,byte[]> mapClassToBytes(String fileName) {261display("class-file\t:" + fileName);262File fileToBeRedefined = new File(classDir + File.separator + fileName);263int fileToRedefineLength = (int )fileToBeRedefined.length();264byte[] arrayToRedefine = new byte[fileToRedefineLength];265266FileInputStream inputFile;267try {268inputFile = new FileInputStream(fileToBeRedefined);269} catch (FileNotFoundException e) {270throw new Failure(UNEXPECTED_STRING + e);271}272273try {274inputFile.read(arrayToRedefine);275inputFile.close();276} catch (IOException e) {277throw new Failure(UNEXPECTED_STRING + e);278}279HashMap<com.sun.jdi.ReferenceType,byte[]> mapForClass = new HashMap<com.sun.jdi.ReferenceType,byte[]>();280mapForClass.put(debugeeClass, arrayToRedefine);281return mapForClass;282}283284private MethodExitRequest createMethodExitRequest(ReferenceType refType) {285EventRequestManager evm = debugee.getEventRequestManager();286MethodExitRequest request = evm.createMethodExitRequest();287request.addClassFilter(refType);288request.enable();289return request;290}291292private void hitBreakpoint(BreakpointEvent event) {293locationInfo(event);294if (event.location().lineNumber() != tc02x001a.checkLastLine) {295complain("BreakpointEvent steps to line " + event.location().lineNumber()296+ ", expected line number is "297+ tc02x001a.checkLastLine);298exitStatus = Consts.TEST_FAILED;299} else {300display("!!!BreakpointEvent steps to the expected line "301+ event.location().lineNumber() + "!!!");302}303display("");304}305306private void hitMethodExit(MethodExitEvent event) {307308locationInfo(event);309310Method mthd = ((MethodExitEvent )event).method();311if (mthd.name().compareTo(tc02x001a.brkpMethodName) == 0) {312Field fld = debugeeClass.fieldByName(tc02x001a.fieldToCheckName);313Value val = debugeeClass.getValue(fld);314if (((IntegerValue )val).value() != tc02x001a.CHANGED_VALUE) {315complain("Unexpected: new code is not actual "316+ "after resetting frames");317complain("Unexpected value of checked field: "318+ val);319exitStatus = Consts.TEST_FAILED;320} else {321display("!!!Expected: new code is actual "322+ "after resetting frames!!!");323}324}325display("");326}327328private void locationInfo(LocatableEvent event) {329display("event info:");330display("\tthread\t- " + event.thread().name());331try {332display("\tsource\t- " + event.location().sourceName());333} catch (AbsentInformationException e) {334}335display("\tmethod\t- " + event.location().method().name());336display("\tline\t- " + event.location().lineNumber());337}338}339340341