Home | History | Annotate | Download | only in Events
      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.Events;
     20 
     21 import java.io.IOException;
     22 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
     23 import org.apache.harmony.jpda.tests.framework.jdwp.Event;
     24 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
     25 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
     26 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
     27 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
     28 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
     29 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.Event_CLASS_PREPARE;
     30 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
     31 
     32 /**
     33  * JDWP unit test for CLASS_PREPARE events sent from the debugger thread.
     34  */
     35 public 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