1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.harmony.jpda.tests.jdwp.VirtualMachine; 20 21 import org.apache.harmony.jpda.tests.framework.TestErrorException; 22 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 23 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 24 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 25 import org.apache.harmony.jpda.tests.framework.jdwp.Value; 26 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase; 27 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 28 29 import java.io.IOException; 30 31 /** 32 * JDWP Unit test for VirtualMachine.Dispose command while a thread is invoking a method. 33 */ 34 public class DisposeDuringInvokeTest extends JDWPSyncTestCase { 35 36 @Override getDebuggeeClassName()37 protected String getDebuggeeClassName() { 38 return DisposeDuringInvokeDebuggee.class.getName(); 39 } 40 41 /** 42 * This testcase exercises VirtualMachine.Dispose command when a thread, suspended by an 43 * event, is still invoking a method. 44 * <BR>At first the test starts DisposeDuringInvokeDebuggee debuggee. 45 * <BR>Then the test sets a breakpoint so that the tested thread (DebuggeeThread) gets suspended 46 * by an event. Once this thread is suspended, we send it an ObjectReference.InvokeMethod 47 * command to initiate a method invocation executing in that thread. The method will synchronize 48 * with the test, waiting for a signal to continue its execution. 49 * <BR>While the tested thread waits for the signal, we send a VirtualMachine.Dispose command to 50 * the debuggee and sends the expected signal so the tested thread completes the method 51 * invocation. 52 * <BR>Finally, we wait for the debuggee's main thread to signal us when the tested thread has 53 * normally terminated after we dispose the JDWP connection. 54 */ testDisposeDuringInvoke()55 public void testDisposeDuringInvoke() { 56 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 57 58 // Set breakpoint so the DebuggeeThread suspends itself only. 59 long classID = getClassIDBySignature(getDebuggeeClassSignature()); 60 long invokedMethodId = getMethodID(classID, 61 DisposeDuringInvokeDebuggee.INVOKED_METHOD_NAME); 62 int breakpointID = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(classID, 63 DisposeDuringInvokeDebuggee.BREAKPOINT_METHOD_NAME, 64 JDWPConstants.SuspendPolicy.EVENT_THREAD); 65 long thisObjectId = getReceiverObjectId(classID); 66 67 // Continue debuggee. 68 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 69 70 // Wait for the DebuggeeThread to suspend on the breakpoint. 71 long threadID = debuggeeWrapper.vmMirror.waitForBreakpoint(breakpointID); 72 73 // Send ObjectReference.InvokeMethod command. 74 CommandPacket command = new CommandPacket( 75 JDWPCommands.ObjectReferenceCommandSet.CommandSetID, 76 JDWPCommands.ObjectReferenceCommandSet.InvokeMethodCommand); 77 command.setNextValueAsThreadID(thisObjectId); 78 command.setNextValueAsThreadID(threadID); 79 command.setNextValueAsClassID(classID); 80 command.setNextValueAsMethodID(invokedMethodId); 81 command.setNextValueAsInt(0); 82 command.setNextValueAsInt(0); 83 try { 84 debuggeeWrapper.vmMirror.sendCommand(command); 85 } catch (IOException e) { 86 throw new TestErrorException("Failed to send ObjectReference.InvokeMethod command", e); 87 } 88 89 // Wait for the DebuggeeThread to start method invocation. 90 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 91 92 // Detach from debuggee with a VirtualMachine.Dispose command. 93 debuggeeWrapper.vmMirror.dispose(); 94 95 // Signal DebuggeeThread to continue so it completes method invocation. 96 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 97 98 // Wait for the DebuggeeThread to terminate. The debuggee's main thread waits for it 99 // (using Thread.join) before signaling us. 100 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 101 102 // The test is a success: resume the debuggee to finish 103 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 104 } 105 106 /** 107 * Returns the object ID of the debuggee object to issue the ObjectReference.InvokeMethod 108 * command. 109 * 110 * @param classID 111 * the debuggee class ID. 112 * @return the object ID of the debuggee 113 */ getReceiverObjectId(long classID)114 private long getReceiverObjectId(long classID) { 115 long thisObjectFieldID = checkField(classID, DisposeDuringInvokeDebuggee.THIS_FIELD_NAME); 116 Value thisObjectValue = 117 debuggeeWrapper.vmMirror.getReferenceTypeValue(classID, thisObjectFieldID); 118 assertEquals("Invalid value tag:", JDWPConstants.Tag.OBJECT_TAG, thisObjectValue.getTag()); 119 return thisObjectValue.getLongValue(); 120 } 121 } 122