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 19package org.apache.harmony.jpda.tests.jdwp.Events; 20 21import java.io.IOException; 22import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 23import org.apache.harmony.jpda.tests.framework.jdwp.Event; 24import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket; 25import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 26import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 27import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent; 28import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 29import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.Event_CLASS_PREPARE; 30import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 31 32/** 33 * JDWP unit test for CLASS_PREPARE events sent from the debugger thread. 34 */ 35public class ClassPrepare002Test extends JDWPEventTestCase { 36 @Override 37 protected String getDebuggeeClassName() { 38 return ClassPrepare002Debuggee.class.getName(); 39 } 40 41 /** 42 * Tests that the CLASS_PREPARE event can be sent from the runtime's debugger thread. 43 * 44 * This test starts by requesting a CLASS_PREPARE event then sends a ReferenceType.GetValues 45 * command to cause the debugger thread to report a CLASS_PREPARE event. After checking the 46 * content of the event packet, we clear the event request then resume the debuggee. 47 */ 48 public void testClassPrepareCausedByDebugger() { 49 logWriter.println("testClassPrepareCausedByDebugger started"); 50 51 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 52 53 // The TestClassA must be loaded but not initialized. 54 long classIDOfA = getClassIDBySignature(getClassSignature(TestClassA.class)); 55 56 // Restrict class prepare only to the tested class. 57 String classPrepareClassName = "org.apache.harmony.jpda.tests.jdwp.Events.TestClassB"; 58 59 // Request CLASS_PREPARE event. The event will be caused by the debugger thread when 60 // handling the ReferenceType.GetValues command we're going to send just after. 61 final byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE; 62 final byte suspendPolicy = JDWPConstants.SuspendPolicy.EVENT_THREAD; 63 Event event = Event.builder(eventKind, suspendPolicy) 64 .setClassMatch(classPrepareClassName) 65 .build(); 66 ReplyPacket eventReply = debuggeeWrapper.vmMirror.setEvent(event); 67 checkReplyPacket(eventReply, "Failed to set CLASS_PREPARE event"); 68 int classPrepareRequestId = eventReply.getNextValueAsInt(); 69 assertAllDataRead(eventReply); 70 71 // Send a ReferenceType.GetValues command to force class initialization. This will trigger 72 // the CLASS_PREPARE event from the debugger thread. 73 logWriter.println("=> CHECK: send ReferenceType.GetValues"); 74 long fieldId = checkField(classIDOfA, "field"); 75 CommandPacket getValuesCommand = new CommandPacket( 76 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 77 JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand); 78 getValuesCommand.setNextValueAsReferenceTypeID(classIDOfA); 79 getValuesCommand.setNextValueAsInt(1); 80 getValuesCommand.setNextValueAsFieldID(fieldId); 81 82 // Send command but does not wait for reply because this will cause a CLASS_PREPARE event 83 // that will suspend every thread. 84 int rtGetValuesCommandId = -1; 85 try { 86 rtGetValuesCommandId = debuggeeWrapper.vmMirror.sendCommand(getValuesCommand); 87 } catch (IOException e) { 88 fail("Failed to send ReferenceType.GetValues command"); 89 } 90 91 // Wait for the class prepare event. 92 EventPacket eventPacket = debuggeeWrapper.vmMirror 93 .receiveCertainEvent(JDWPConstants.EventKind.CLASS_PREPARE); 94 ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket); 95 assertNotNull(parsedEvents); 96 logWriter.println("Received " + parsedEvents.length + " event(s)"); 97 assertEquals(1, parsedEvents.length); 98 99 // Check event is the expected one. 100 ParsedEvent parsedEvent = parsedEvents[0]; 101 // Only expect CLASS_PREPARE event. 102 assertEquals(JDWPConstants.EventKind.CLASS_PREPARE, parsedEvent.getEventKind()); 103 // CLASS_PREPARE events caused by the debugger must have an ALL 104 // suspend policy. 105 assertEquals(JDWPConstants.SuspendPolicy.ALL, parsedEvent.getSuspendPolicy()); 106 // Check that its the event that we have requested. 107 assertEquals(classPrepareRequestId, parsedEvent.getRequestID()); 108 Event_CLASS_PREPARE classPrepareEvent = (Event_CLASS_PREPARE) parsedEvent; 109 // The JDWP spec says that if the event was caused by the debugger thread, the thread ID 110 // must be 0. 111 assertEquals(0, classPrepareEvent.getThreadID()); 112 // Check that it is the expected class. 113 assertEquals(getClassSignature(classPrepareClassName), classPrepareEvent.getSignature()); 114 115 // Check that we received the reply of the command that caused the CLASS_PREPARE event. 116 logWriter.println("=> CHECK: receive ReferenceType.GetValues reply (" + 117 rtGetValuesCommandId + ")"); 118 ReplyPacket getValuesReply = null; 119 try { 120 getValuesReply = debuggeeWrapper.vmMirror.receiveReply(rtGetValuesCommandId); 121 } catch (InterruptedException | IOException e) { 122 fail("Failed to receive ReferenceType.GetValues reply"); 123 } 124 checkReplyPacket(getValuesReply, "Failed to receive ReferenceType.GetValues reply"); 125 126 // Clear the CLASS_PREPARE event request. 127 debuggeeWrapper.vmMirror.clearEvent(JDWPConstants.EventKind.CLASS_PREPARE, 128 classPrepareRequestId); 129 130 // Resume all threads suspended by the CLASS_PREPARE event. 131 debuggeeWrapper.vmMirror.resume(); 132 133 // Let the debuggee finish. 134 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 135 136 logWriter.println("testClassPrepareCausedByDebugger finished"); 137 } 138} 139