/******************************************************************************* * Copyright (c) 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.debug.tests.state; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.model.ILineBreakpoint; import org.eclipse.debug.core.model.IThread; import org.eclipse.jdi.internal.jdwp.JdwpPacket; import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket; import org.eclipse.jdt.debug.core.IJavaBreakpoint; import org.eclipse.jdt.debug.core.IJavaDebugTarget; import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; import org.eclipse.jdt.debug.core.IJavaObject; import org.eclipse.jdt.debug.core.IJavaThread; import org.eclipse.jdt.debug.testplugin.DebugElementEventWaiter; import org.eclipse.jdt.debug.tests.AbstractDebugTest; /** * Tests that state refresh works after modifying the target state * with a custom JDWP command. * * @since 3.6 */ public class RefreshStateTests extends AbstractDebugTest { public RefreshStateTests(String name) { super(name); } /** * Resume a thread behind the scenes and ensure model state updates appropriately. * * @throws CoreException */ public void testThreadHasResumed() throws Exception { String typeName = "org.eclipse.debug.tests.targets.CallLoop"; ILineBreakpoint bp = createLineBreakpoint(16, "org.eclipse.debug.tests.targets.Looper"); IJavaThread thread = null; try { thread= launchToLineBreakpoint(typeName, bp); IJavaDebugTarget jdiTarget = (IJavaDebugTarget) thread.getDebugTarget(); // Resume thread (set 11, command 3) IJavaObject reference = thread.getThreadObject(); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); DataOutputStream outData = new DataOutputStream(outBytes); outData.writeLong(reference.getUniqueId()); byte[] reply = jdiTarget.sendCommand((byte)11, (byte)3, outBytes.toByteArray()); JdwpReplyPacket packet = (JdwpReplyPacket) JdwpPacket.build(reply); assertEquals("Unexpected error code in reply packet", 0, packet.errorCode()); // model should still be suspended assertTrue("Model should be in suspended state", thread.isSuspended()); // refresh the model, expect a resume event DebugElementEventWaiter waiter = new DebugElementEventWaiter(DebugEvent.RESUME, thread); jdiTarget.refreshState(); Object source = waiter.waitForEvent(); assertNotNull("Thread never sent resume event", source); assertEquals("Wrong thread resumed", thread, source); // model should now be in running state assertFalse("Model should now be running", thread.isSuspended()); } finally { terminateAndRemove(thread); removeAllBreakpoints(); } } /** * Resume all threads behind the scenes and ensure model state updates appropriately. * * @throws CoreException */ public void testAllThreadsResumed() throws Exception { String typeName = "org.eclipse.debug.tests.targets.CallLoop"; IJavaLineBreakpoint bp = createLineBreakpoint(16, "org.eclipse.debug.tests.targets.Looper"); bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_VM); IJavaThread thread = null; try { thread= launchToLineBreakpoint(typeName, bp); IJavaDebugTarget jdiTarget = (IJavaDebugTarget) thread.getDebugTarget(); // Resume each thread (set 11, command 3) IThread[] threads = jdiTarget.getThreads(); for (int i = 0; i < threads.length; i++) { IJavaThread jThread = (IJavaThread) threads[i]; IJavaObject reference = jThread.getThreadObject(); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); DataOutputStream outData = new DataOutputStream(outBytes); outData.writeLong(reference.getUniqueId()); byte[] reply = jdiTarget.sendCommand((byte)11, (byte)3, outBytes.toByteArray()); JdwpReplyPacket packet = (JdwpReplyPacket) JdwpPacket.build(reply); assertEquals("Unexpected error code in reply packet", 0, packet.errorCode()); } // model should still be suspended assertTrue("Model should be in suspended state", jdiTarget.isSuspended()); // refresh the model, expect a resume event DebugElementEventWaiter waiter = new DebugElementEventWaiter(DebugEvent.RESUME, jdiTarget); jdiTarget.refreshState(); Object source = waiter.waitForEvent(); assertNotNull("Thread never sent resume event", source); // model should now be in running state assertFalse("Model should now be running", jdiTarget.isSuspended()); } finally { terminateAndRemove(thread); removeAllBreakpoints(); } } /** * Suspend a thread behind the scenes and ensure model state updates appropriately. * * @throws CoreException */ public void testThreadHasSuspended() throws Exception { String typeName = "org.eclipse.debug.tests.targets.CallLoop"; ILineBreakpoint bp = createLineBreakpoint(16, "org.eclipse.debug.tests.targets.Looper"); IJavaThread thread = null; try { thread= launchToLineBreakpoint(typeName, bp); IJavaDebugTarget jdiTarget = (IJavaDebugTarget) thread.getDebugTarget(); // resume the thread to get into running state DebugElementEventWaiter waiter = new DebugElementEventWaiter(DebugEvent.RESUME, thread); thread.resume(); waiter.waitForEvent(); // model should now be in running state assertFalse("Model should now be running", thread.isSuspended()); // suspend the thread with a JDWP command (set 11, command 2) IJavaObject reference = thread.getThreadObject(); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); DataOutputStream outData = new DataOutputStream(outBytes); outData.writeLong(reference.getUniqueId()); byte[] reply = jdiTarget.sendCommand((byte)11, (byte)2, outBytes.toByteArray()); JdwpReplyPacket packet = (JdwpReplyPacket) JdwpPacket.build(reply); assertEquals("Unexpected error code in reply packet", 0, packet.errorCode()); // model should still be running assertFalse("Model should be in running state", thread.isSuspended()); // refresh the model, expect a suspend event waiter = new DebugElementEventWaiter(DebugEvent.SUSPEND, thread); jdiTarget.refreshState(); Object source = waiter.waitForEvent(); assertNotNull("Thread never sent suspend event", source); assertEquals("Wrong thread suspended", thread, source); // model should be suspended now assertTrue("Model should be in suspended state", thread.isSuspended()); } finally { terminateAndRemove(thread); removeAllBreakpoints(); } } /** * Suspend all threads behind the scenes and ensure model state updates appropriately. * * @throws CoreException */ public void testAllThreadsSuspended() throws Exception { String typeName = "org.eclipse.debug.tests.targets.CallLoop"; ILineBreakpoint bp = createLineBreakpoint(16, "org.eclipse.debug.tests.targets.Looper"); IJavaThread thread = null; try { thread= launchToLineBreakpoint(typeName, bp); IJavaDebugTarget jdiTarget = (IJavaDebugTarget) thread.getDebugTarget(); // resume the thread to get into running state DebugElementEventWaiter waiter = new DebugElementEventWaiter(DebugEvent.RESUME, thread); thread.resume(); waiter.waitForEvent(); // model should now be in running state assertFalse("Model should now be running", thread.isSuspended()); IThread[] threads = jdiTarget.getThreads(); for (int i = 0; i < threads.length; i++) { IJavaThread jThread = (IJavaThread) threads[i]; // suspend each thread with a JDWP command (set 11, command 2) IJavaObject reference = jThread.getThreadObject(); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); DataOutputStream outData = new DataOutputStream(outBytes); outData.writeLong(reference.getUniqueId()); byte[] reply = jdiTarget.sendCommand((byte)11, (byte)2, outBytes.toByteArray()); JdwpReplyPacket packet = (JdwpReplyPacket) JdwpPacket.build(reply); assertEquals("Unexpected error code in reply packet", 0, packet.errorCode()); } // model should still be running assertFalse("Model should be in running state", jdiTarget.isSuspended()); // refresh the model, expect a suspend event waiter = new DebugElementEventWaiter(DebugEvent.SUSPEND, jdiTarget); jdiTarget.refreshState(); Object source = waiter.waitForEvent(); assertNotNull("Target never sent suspend event", source); // model should be suspended now assertTrue("Model should be in suspended state", jdiTarget.isSuspended()); } finally { terminateAndRemove(thread); removeAllBreakpoints(); } } /** * Suspend the entire target behind the scenes and ensure model state updates appropriately. * * @throws CoreException */ public void testTargetHasSuspended() throws Exception { String typeName = "org.eclipse.debug.tests.targets.CallLoop"; ILineBreakpoint bp = createLineBreakpoint(16, "org.eclipse.debug.tests.targets.Looper"); IJavaThread thread = null; try { thread= launchToLineBreakpoint(typeName, bp); IJavaDebugTarget jdiTarget = (IJavaDebugTarget) thread.getDebugTarget(); // resume the thread to get into running state DebugElementEventWaiter waiter = new DebugElementEventWaiter(DebugEvent.RESUME, thread); thread.resume(); waiter.waitForEvent(); // model should now be in running state assertFalse("Model should now be running", thread.isSuspended()); // suspend the target with a JDWP command (set 1, command 8) IJavaObject reference = thread.getThreadObject(); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); DataOutputStream outData = new DataOutputStream(outBytes); outData.writeLong(reference.getUniqueId()); byte[] reply = jdiTarget.sendCommand((byte)1, (byte)8, outBytes.toByteArray()); JdwpReplyPacket packet = (JdwpReplyPacket) JdwpPacket.build(reply); assertEquals("Unexpected error code in reply packet", 0, packet.errorCode()); // model should still be running assertFalse("Model should be in running state", jdiTarget.isSuspended()); // refresh the model, expect a suspend event waiter = new DebugElementEventWaiter(DebugEvent.SUSPEND, jdiTarget); jdiTarget.refreshState(); Object source = waiter.waitForEvent(); assertNotNull("Target never sent suspend event", source); // model should be suspended now assertTrue("Model should be in suspended state", jdiTarget.isSuspended()); } finally { terminateAndRemove(thread); removeAllBreakpoints(); } } /** * Resume a target behind the scenes and ensure model state updates appropriately. * * @throws CoreException */ public void testTargetHasResumed() throws Exception { String typeName = "org.eclipse.debug.tests.targets.CallLoop"; IJavaLineBreakpoint bp = createLineBreakpoint(16, "org.eclipse.debug.tests.targets.Looper"); bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_VM); IJavaThread thread = null; try { thread= launchToLineBreakpoint(typeName, bp); IJavaDebugTarget jdiTarget = (IJavaDebugTarget) thread.getDebugTarget(); // Resume target (set 1, command 9) IJavaObject reference = thread.getThreadObject(); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); DataOutputStream outData = new DataOutputStream(outBytes); outData.writeLong(reference.getUniqueId()); byte[] reply = jdiTarget.sendCommand((byte)1, (byte)9, outBytes.toByteArray()); JdwpReplyPacket packet = (JdwpReplyPacket) JdwpPacket.build(reply); assertEquals("Unexpected error code in reply packet", 0, packet.errorCode()); // model should still be suspended assertTrue("Model should be in suspended state", jdiTarget.isSuspended()); // refresh the model, expect a resume event DebugElementEventWaiter waiter = new DebugElementEventWaiter(DebugEvent.RESUME, jdiTarget); jdiTarget.refreshState(); Object source = waiter.waitForEvent(); assertNotNull("Target never sent resume event", source); // model should now be in running state assertFalse("Model should now be running", jdiTarget.isSuspended()); } finally { terminateAndRemove(thread); removeAllBreakpoints(); } } }