001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.debug.jdi.tests;
011:
012: import com.sun.jdi.IncompatibleThreadStateException;
013: import com.sun.jdi.Location;
014: import com.sun.jdi.ReferenceType;
015: import com.sun.jdi.StackFrame;
016: import com.sun.jdi.ThreadReference;
017: import com.sun.jdi.event.ClassPrepareEvent;
018: import com.sun.jdi.event.ClassUnloadEvent;
019: import com.sun.jdi.event.Event;
020: import com.sun.jdi.event.StepEvent;
021: import com.sun.jdi.request.ClassPrepareRequest;
022: import com.sun.jdi.request.ClassUnloadRequest;
023: import com.sun.jdi.request.EventRequest;
024: import com.sun.jdi.request.StepRequest;
025:
026: /**
027: * Tests for the hot code replacement JDI extension.
028: */
029: public class HotCodeReplacementTest extends AbstractJDITest {
030: /**
031: * Creates a new test.
032: */
033: public HotCodeReplacementTest() {
034: super ();
035: }
036:
037: private void dropTopFrame(ThreadReference thread,
038: org.eclipse.jdi.hcr.ThreadReference hcrThread) {
039: // Get stack size
040: int stackSize = 0;
041: try {
042: stackSize = thread.frames().size();
043: } catch (IncompatibleThreadStateException e) {
044: assertTrue("dropTopFrame.1", false);
045: }
046:
047: // Create and install step out request
048: StepRequest request = fVM.eventRequestManager()
049: .createStepRequest(thread, StepRequest.STEP_MIN,
050: StepRequest.STEP_OUT);
051: request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
052: request.enable();
053:
054: // Prepare to receive the event
055: EventWaiter waiter = new EventWaiter(request, false);
056: fEventReader.addEventListener(waiter);
057:
058: // Do return
059: boolean finallyBlocksSkipped = hcrThread.doReturn(null, true);
060: assertTrue("dropTopFrame.2", !finallyBlocksSkipped);
061:
062: // Wait for the event to come in
063: Event event = waitForEvent(waiter, 10000); // Wait 10s max
064: assertTrue("dropTopFrame.3", event != null);
065: fEventReader.removeEventListener(waiter);
066: fVM.eventRequestManager().deleteEventRequest(request);
067:
068: // Check thread has dropped top frame
069: assertTrue("dropTopFrame.4", thread.isSuspended());
070: int newStackSize = 0;
071: try {
072: newStackSize = thread.frames().size();
073: } catch (IncompatibleThreadStateException e) {
074: assertTrue("dropTopFrame.5", false);
075: }
076: assertEquals("dropTopFrame.6", stackSize - 1, newStackSize);
077: }
078:
079: /**
080: * Init the fields that are used by this test only.
081: */
082: public void localSetUp() {
083: waitUntilReady();
084: }
085:
086: /**
087: * Run all tests and output to standard output.
088: * @param args
089: */
090: public static void main(String[] args) {
091: new HotCodeReplacementTest().runSuite(args);
092: }
093:
094: /**
095: * Gets the name of the test case.
096: * @see junit.framework.TestCase#getName()
097: */
098: public String getName() {
099: return "Hot code replacement extension to JDI (org.eclipse.jdi.hcr) tests";
100: }
101:
102: private void reenterOnExit(ThreadReference thread) {
103: // Get top frame's location
104: Location location = null;
105: try {
106: StackFrame frame = (StackFrame) thread.frames(0, 1).get(0);
107: location = frame.location();
108: } catch (IncompatibleThreadStateException e) {
109: assertTrue("reenterOnExit.1", false);
110: }
111:
112: // Create and install reenter step request
113: org.eclipse.jdi.hcr.EventRequestManager eventRequestManager = (org.eclipse.jdi.hcr.EventRequestManager) fVM
114: .eventRequestManager();
115: org.eclipse.jdi.hcr.ReenterStepRequest request = eventRequestManager
116: .createReenterStepRequest(thread);
117: request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
118: request.enable();
119:
120: // Prepare to receive the step event
121: EventWaiter waiter = new EventWaiter(request, false);
122: fEventReader.addEventListener(waiter);
123:
124: // Resume thread with a doReturn so that the frame is reentered right away
125: ((org.eclipse.jdi.hcr.ThreadReference) thread).doReturn(null,
126: false);
127:
128: // Wait for the step event to come in
129: StepEvent event = (StepEvent) waitForEvent(waiter, 10000); // Wait 10s max
130: assertTrue("reenterOnExit.2", event != null);
131: fEventReader.removeEventListener(waiter);
132: fVM.eventRequestManager().deleteEventRequest(request);
133:
134: // Check that the top frame location is as expected
135: Location newLocation = null;
136: try {
137: StackFrame frame = (StackFrame) thread.frames(0, 1).get(0);
138: newLocation = frame.location();
139: } catch (IncompatibleThreadStateException e) {
140: assertTrue("reenterOnExit.3", false);
141: }
142: assertTrue("reenterOnExit.4", !newLocation.equals(location));
143: assertTrue("reenterOnExit.5",
144: newLocation.codeIndex() <= location.codeIndex());
145:
146: }
147:
148: private void reloadClasses() {
149: // Gets the old class
150: ReferenceType oldType = getMainClass();
151:
152: // Create and install class unload and class prepare event requests
153: ClassUnloadRequest unloadRequest = fVM.eventRequestManager()
154: .createClassUnloadRequest();
155: unloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
156: unloadRequest.enable();
157: ClassPrepareRequest loadRequest = fVM.eventRequestManager()
158: .createClassPrepareRequest();
159: loadRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
160: loadRequest.enable();
161:
162: // Prepare to receive the class unload event
163: EventWaiter unloadEventWaiter = new EventWaiter(unloadRequest,
164: true);
165: fEventReader.addEventListener(unloadEventWaiter);
166:
167: // Prepare to receive the class prepare event
168: EventWaiter loadEventWaiter = new EventWaiter(loadRequest, true);
169: fEventReader.addEventListener(loadEventWaiter);
170:
171: // Reload classes
172: org.eclipse.jdi.hcr.VirtualMachine vm = (org.eclipse.jdi.hcr.VirtualMachine) fVM;
173: int result = vm
174: .classesHaveChanged(new String[] { "org.eclipse.debug.jdi.tests.program.MainClass" });
175: assertEquals("reloadClasses.1",
176: org.eclipse.jdi.hcr.VirtualMachine.RELOAD_SUCCESS,
177: result);
178:
179: // Wait for the class unload event to come in
180: ClassUnloadEvent unloadEvent = (ClassUnloadEvent) waitForEvent(
181: unloadEventWaiter, 10000);
182: // Wait 10s max
183: assertTrue("reloadClasses.2", unloadEvent != null);
184: fEventReader.removeEventListener(unloadEventWaiter);
185: fVM.eventRequestManager().deleteEventRequest(unloadRequest);
186: assertEquals("reloadClasses.3",
187: "org.eclipse.debug.jdi.tests.program.MainClass",
188: unloadEvent.className());
189:
190: // Wait for the class prepare event to come in
191: ClassPrepareEvent loadEvent = (ClassPrepareEvent) waitForEvent(
192: loadEventWaiter, 10000);
193: // Wait 10s max
194: assertTrue("reloadClasses.4", loadEvent != null);
195: fEventReader.removeEventListener(loadEventWaiter);
196: fVM.eventRequestManager().deleteEventRequest(loadRequest);
197: ReferenceType newType = loadEvent.referenceType();
198: assertEquals("reloadClasses.5",
199: "org.eclipse.debug.jdi.tests.program.MainClass",
200: newType.name());
201: assertTrue("reloadClasses.6", !oldType.equals(newType));
202: }
203:
204: /**
205: * Use case 1:
206: * . get a thread and suspend it
207: * . get hot code replacement capabilities
208: * . drop the top a frame
209: * . reload some classes
210: * . request reeenter on exit
211: * . resume thread
212: * . get step event
213: * . get class file version for some classes
214: */
215: public void testJDIUseCase1() {
216: // Get the suspended thread
217: ThreadReference thread = getThread();
218: assertTrue("1", thread.isSuspended());
219: assertEquals("2", 1, thread.suspendCount());
220: org.eclipse.jdi.hcr.ThreadReference hcrThread = (org.eclipse.jdi.hcr.ThreadReference) thread;
221:
222: org.eclipse.jdi.hcr.VirtualMachine vm = (org.eclipse.jdi.hcr.VirtualMachine) fVM;
223:
224: // Drop the top a frame
225: try {
226: if (vm.canDoReturn()) {
227: dropTopFrame(thread, hcrThread);
228: }
229: } catch (UnsupportedOperationException e) {
230: //not using a VM that supports the extension
231: return;
232: }
233:
234: // Reload classes
235: if (vm.canReloadClasses())
236: reloadClasses();
237:
238: // Reenter on exit
239: if (vm.canReenterOnExit())
240: reenterOnExit(thread);
241: }
242:
243: /**
244: * Make sure the test leaves the VM in the same state it found it.
245: */
246: public void localTearDown() {
247: waitUntilReady();
248: }
249: }
|