1f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz/* 2f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Licensed to the Apache Software Foundation (ASF) under one or more 3f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * contributor license agreements. See the NOTICE file distributed with 4f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * this work for additional information regarding copyright ownership. 5f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * The ASF licenses this file to You under the Apache License, Version 2.0 6f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * (the "License"); you may not use this file except in compliance with 7f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * the License. You may obtain a copy of the License at 8f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 9f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * http://www.apache.org/licenses/LICENSE-2.0 10f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 11f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Unless required by applicable law or agreed to in writing, software 12f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * distributed under the License is distributed on an "AS IS" BASIS, 13f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 15f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * See the License for the specific language governing permissions and 16f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * limitations under the License. 17f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz */ 18f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 19f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzpackage org.apache.harmony.jpda.tests.jdwp.share; 20f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 21f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport org.apache.harmony.jpda.tests.framework.TestErrorException; 22f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 23f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 24f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 25f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport org.apache.harmony.jpda.tests.jdwp.share.debuggee.InvokeMethodWithSuspensionDebuggee; 26f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 27f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 28f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzimport java.io.IOException; 29f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 30f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz/** 31f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Base class for tests checking invoke command with thread suspension. 32f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz */ 33f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertzpublic abstract class JDWPInvokeMethodWithSuspensionTestCase extends JDWPSyncTestCase { 34f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 35f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz @Override 36f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz protected final String getDebuggeeClassName() { 37f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz return InvokeMethodWithSuspensionDebuggee.class.getName(); 38f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz } 39f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 40f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz /** 41f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * This methods runs the {@link InvokeMethodWithSuspensionDebuggee} then sets up the 42f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * following breakpoints: 43f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * - breakpoint #1 to suspend the current thread only when the debuggee starts 44f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * - breakpoint #2 to suspend all threads from a new thread started by a method called through 45f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * JDWP. 46f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * When we receive the event for breakpoint #1, we issue a request to invoke a method (or a 47f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * constructor) in the event thread (suspended on the breakpoint). The event thread starts 48f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * another child thread and loops as long as the child is running. However, we do not read the 49f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * reply of the invoke yet. 50f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Next, we wait for the new thread to hit breakpoint #2. We resume all threads in the debuggee 51f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * and read the reply of the invoke. 52f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Finally, we resume the thread that completed the invoke. 53f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 54f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @param invokedMethodName 55f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * the name of the method to invoke 56f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz */ 57f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz protected void runInvokeMethodTest(String invokedMethodName) { 58f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Wait for debuggee to start. 59f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 60f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 61f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz long classID = getClassIDBySignature(getDebuggeeClassSignature()); 62f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz long invokeMethodID = getMethodID(classID, invokedMethodName); 63f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 64f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Set breakpoint with EVENT_THREAD suspend policy so only the event thread is suspended. 65f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // We will invoke the method in this thread. 66f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz int breakpointEventThread = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(classID, 67f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz InvokeMethodWithSuspensionDebuggee.BREAKPOINT_EVENT_THREAD_METHOD_NAME, 68f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz JDWPConstants.SuspendPolicy.EVENT_THREAD); 69f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 70f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Set breakpoint with ALL suspend policy to suspend all threads. The thread started 71f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // during the invoke will suspend all threads, including the thread executing the invoke. 72f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz int breakpointAllThreads = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(classID, 73f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz InvokeMethodWithSuspensionDebuggee.BREAKPOINT_ALL_THREADS_METHOD_NAME, 74f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz JDWPConstants.SuspendPolicy.ALL); 75f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 76f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Tell the debuggee to continue. 77f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 78f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 79f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Wait for breakpoint and get id of suspended thread. 80f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz long eventThreadOne = debuggeeWrapper.vmMirror.waitForBreakpoint(breakpointEventThread); 81f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz int suspendCount = debuggeeWrapper.vmMirror.getThreadSuspendCount(eventThreadOne); 82f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz assertEquals("Invalid suspend count:", 1, suspendCount); 83f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 84f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Send command but does not read reply now. That invoked method starts another thread 85f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // that is going to hit a breakpoint and suspend all threads, including the thread invoking 86f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // the method. The invoke can only complete when that new thread terminates, which requires 87f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // we send a VirtualMachine.Resume command. 88f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz final int invoke_options = 0; // resume/suspend all threads before/after the invoke. 89f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz CommandPacket invokeMethodCommand = buildInvokeCommand(eventThreadOne, classID, 90f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz invokeMethodID, invoke_options); 91f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 92f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz String commandName = getInvokeCommandName(); 93f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz logWriter.println("Send " + commandName); 94f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz int invokeMethodCommandID = -1; 95f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz try { 96f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz invokeMethodCommandID = debuggeeWrapper.vmMirror.sendCommand(invokeMethodCommand); 97f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz } catch (IOException e) { 98f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz logWriter.printError("Failed to send " + commandName, e); 99f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz fail(); 100f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz } 101f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 102f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Wait for 2nd breakpoint to hit. 103f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz long eventThreadTwo = debuggeeWrapper.vmMirror.waitForBreakpoint(breakpointAllThreads); 104f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz suspendCount = debuggeeWrapper.vmMirror.getThreadSuspendCount(eventThreadTwo); 105f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz assertEquals("Invalid suspend count:", 1, suspendCount); 106f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 107f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // At this point, the event thread #1 must have been suspended by event thread #2. Since 108f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // the invoke has resumed it too, its suspend count must remain 1. 109f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz suspendCount = debuggeeWrapper.vmMirror.getThreadSuspendCount(eventThreadOne); 110f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz assertEquals("Invalid suspend count:", 1, suspendCount); 111f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 112f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Test that sending another invoke command in the same thread returns an error. 113f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz CommandPacket anotherInvokeMethodCommand = buildInvokeCommand(eventThreadOne, classID, 114f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz invokeMethodID, invoke_options); 115f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz ReplyPacket anotherInvokeMethodReply = 116f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz debuggeeWrapper.vmMirror.performCommand(anotherInvokeMethodCommand); 117f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // The RI returns INVALID_THREAD error while ART returns ALREADY_INVOKING error which is 118f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // more accurate. We only test we get an error so we can run the test with both runtimes. 119f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz assertTrue("Expected an error", 120f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz anotherInvokeMethodReply.getErrorCode() != JDWPConstants.Error.NONE); 121f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 122f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Send a VirtualMachine.Resume to resume all threads. This will unblock the event thread 123f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // with the invoke in-progress. 124f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz logWriter.println("Resume all threads"); 125f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz resumeDebuggee(); 126f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 127f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // Now we can read the invoke reply. 128f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz ReplyPacket invokeMethodReply = null; 129f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz try { 130f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz logWriter.println("Receiving reply for command " + invokeMethodCommandID + " ..."); 131f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz invokeMethodReply = debuggeeWrapper.vmMirror.receiveReply(invokeMethodCommandID); 132f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz } catch (Exception e) { 133f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz throw new TestErrorException("Did not receive invoke reply", e); 134f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz } 135f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz checkReplyPacket(invokeMethodReply, commandName + " command"); 136f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz logWriter.println("Received reply for command " + invokeMethodCommandID + " OK"); 137f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 138f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz checkInvokeReply(invokeMethodReply); 139f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 140f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz // The invoke is complete but the thread is still suspended: let's resume it now. 141f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz suspendCount = debuggeeWrapper.vmMirror.getThreadSuspendCount(eventThreadOne); 142f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz assertEquals("Invalid suspend count:", 1, suspendCount); 143f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 144f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz logWriter.println("Resume event thread #1"); 145f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz debuggeeWrapper.vmMirror.resumeThread(eventThreadOne); 146f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz } 147f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 148f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz /** 149f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Builds the packed for the tested JDWP command. 150f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 151f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @param threadId 152f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * the id of the thread that will invoke the method 153f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @param classID 154f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * the class ID of the invoked method 155f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @param methodId 156f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * the ID of the invoke method 157f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @param invokeOptions 158f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * options for the invoke 159f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @return a command 160f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz */ 161f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz protected abstract CommandPacket buildInvokeCommand(long threadId, long classID, 162f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz long methodId, int invokeOptions); 163f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 164f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz /** 165f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Returns the name of the command returned by {@link #buildInvokeCommand} for printing. 166f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 167f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @return the name of the invoke command sent to the debuggee 168f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz */ 169f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz protected abstract String getInvokeCommandName(); 170f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 171f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz /** 172f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * Checks the reply for the tested JDWP command. 173f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * 174f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz * @param reply the reply of the invoke 175f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz */ 176f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz protected abstract void checkInvokeReply(ReplyPacket reply); 177f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz 178f8670f3c29626892e32d30aa00ce8e4b94bd9609Sebastien Hertz} 179