Home | History | Annotate | Download | only in ReferenceType
      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 /**
     20  * @author Anatoly F. Bondarenko
     21  */
     22 
     23 /**
     24  * Created on 16.02.2005
     25  */
     26 package org.apache.harmony.jpda.tests.jdwp.ReferenceType;
     27 
     28 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
     29 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
     30 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
     31 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
     32 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
     33 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
     34 
     35 
     36 /**
     37  * JDWP Unit test for ReferenceType.ClassLoader command.
     38  */
     39 public class ClassLoaderTest extends JDWPSyncTestCase {
     40 
     41     static final int testStatusPassed = 0;
     42     static final int testStatusFailed = -1;
     43     static final String thisCommandName = "ReferenceType.ClassLoader command";
     44     static final String debuggeeSignature = "Lorg/apache/harmony/jpda/tests/jdwp/share/debuggee/HelloWorld;";
     45 
     46     @Override
     47     protected String getDebuggeeClassName() {
     48         return "org.apache.harmony.jpda.tests.jdwp.share.debuggee.HelloWorld";
     49     }
     50 
     51     /**
     52      * This testcase exercises ReferenceType.ClassLoader command.
     53      * <BR>The test starts HelloWorld debuggee, requests referenceTypeId
     54      * for it by VirtualMachine.ClassesBySignature command, then
     55      * performs ReferenceType.ClassLoader command and checks that command
     56      * returns reply with some non-zero classLoaderID without any ERROR
     57      */
     58     public void testClassLoader001() {
     59         classLoaderTest("testClassLoader001", debuggeeSignature, false);
     60     }
     61 
     62     /**
     63      * Same as testClassLoader001, but expecting a zero classLoaderId for
     64      * a boot classpath class.
     65      * @see <a href="http://docs.oracle.com/javase/7/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType_ClassLoader">ReferenceType.ClassLoader</a>
     66      * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jpda/jdwp-spec.html">Common Data Types</a>
     67      */
     68     public void testClassLoader002() {
     69         classLoaderTest("testClassLoader002", "Ljava/lang/Object;", true);
     70     }
     71 
     72     /**
     73      * Test that supplying a general object that is not a class returns
     74      * a class error.
     75      */
     76     public void testClassLoader003() {
     77         String thisTestName = "testClassLoader003";
     78         logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": START...");
     79         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
     80 
     81         // It's easer to just ask for an instance of String (as we know the runtime has
     82         // created some during startup), rather than collecting all the constructor data
     83         // for a class like the debuggee.
     84         long stringClassRefTypeID = getClassIDBySignature("Ljava/lang/String;");
     85 
     86         CommandPacket stringInstanceCommand = new CommandPacket(
     87                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
     88                 JDWPCommands.ReferenceTypeCommandSet.InstancesCommand);
     89         stringInstanceCommand.setNextValueAsReferenceTypeID(stringClassRefTypeID);
     90         stringInstanceCommand.setNextValueAsInt(1);  // One instance is enough.
     91         ReplyPacket stringInstanceReply =
     92                 debuggeeWrapper.vmMirror.performCommand(stringInstanceCommand);
     93         checkReplyPacket(stringInstanceReply, "ReferenceType.Instances");
     94         int stringInstanceCount = stringInstanceReply.getNextValueAsInt();
     95         assertTrue("Expected to get one string instance", stringInstanceCount == 1);
     96         long stringInstanceID = stringInstanceReply.getNextValueAsTaggedObject().objectID;
     97 
     98         CommandPacket classLoaderCommand = new CommandPacket(
     99                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    100                 JDWPCommands.ReferenceTypeCommandSet.ClassLoaderCommand);
    101         classLoaderCommand.setNextValueAsReferenceTypeID(stringInstanceID);
    102         ReplyPacket classLoaderReply = debuggeeWrapper.vmMirror.performCommand(classLoaderCommand);
    103         checkReplyPacket(classLoaderReply, thisCommandName, JDWPConstants.Error.INVALID_CLASS);
    104 
    105         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
    106         logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH");
    107     }
    108 
    109     /**
    110      * Implementation of tests 001 and 002, using the given parameters.
    111      */
    112     private void classLoaderTest(String thisTestName, String signature, boolean expectZero) {
    113         logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": START...");
    114         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
    115 
    116         long refTypeID = getClassIDBySignature(signature);
    117 
    118         logWriter.println("=> Debuggee class = " + signature);
    119         logWriter.println("=> referenceTypeID for Debuggee class = " + refTypeID);
    120         logWriter.println("=> CHECK1: send " + thisCommandName + " and check reply for ERROR...");
    121 
    122         CommandPacket classLoaderCommand = new CommandPacket(
    123                 JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
    124                 JDWPCommands.ReferenceTypeCommandSet.ClassLoaderCommand);
    125         classLoaderCommand.setNextValueAsReferenceTypeID(refTypeID);
    126 
    127         ReplyPacket classLoaderReply = debuggeeWrapper.vmMirror.performCommand(classLoaderCommand);
    128         classLoaderCommand = null;
    129         checkReplyPacket(classLoaderReply, thisCommandName);
    130 
    131         long returnedClassLoaderID = classLoaderReply.getNextValueAsObjectID();
    132         if (expectZero) {
    133             assertTrue("Should be boot classpath classloader", returnedClassLoaderID == 0);
    134         } else {
    135             assertTrue("Should not be boot classpath classloader", returnedClassLoaderID != 0);
    136         }
    137         logWriter.println("=> CHECK1: PASSED: Returned classLoaderID = " + returnedClassLoaderID);
    138 
    139         assertAllDataRead(classLoaderReply);
    140 
    141         assertTrue("Result should be a classloader", isClassLoader(returnedClassLoaderID));
    142 
    143         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
    144         logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH");
    145     }
    146 
    147     /**
    148      * Helper to check whether an object is a classloader. Works by getting the class and
    149      * the reference ID of java.lang.ClassLoader, then following the superclass chain and
    150      * comparing.
    151      */
    152     private boolean isClassLoader(long classLoaderObjectID) {
    153         if (classLoaderObjectID == 0) {
    154             // 0 = null = bootstrap classloader.
    155             return true;
    156         }
    157 
    158         CommandPacket refTypeCommand = new CommandPacket(
    159                 JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
    160                 JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand);
    161         refTypeCommand.setNextValueAsObjectID(classLoaderObjectID);
    162         ReplyPacket refTypeReply = debuggeeWrapper.vmMirror.performCommand(refTypeCommand);
    163         checkReplyPacket(refTypeReply, "ObjectReference.ReferenceType");
    164         refTypeReply.getNextValueAsByte();  // kind.
    165         long classLoaderClassRefTypeID = refTypeReply.getNextValueAsReferenceTypeID();
    166 
    167         long baseClassLoaderRefTypeID = getClassIDBySignature("Ljava/lang/ClassLoader;");
    168 
    169         while (classLoaderClassRefTypeID != 0) {
    170             if (classLoaderClassRefTypeID == baseClassLoaderRefTypeID) {
    171                 // This is a classloader...
    172                 return true;
    173             }
    174             CommandPacket superclassCommand = new CommandPacket(
    175                 JDWPCommands.ClassTypeCommandSet.CommandSetID,
    176                 JDWPCommands.ClassTypeCommandSet.SuperclassCommand);
    177             superclassCommand.setNextValueAsObjectID(classLoaderClassRefTypeID);
    178             ReplyPacket superclassReply =
    179                     debuggeeWrapper.vmMirror.performCommand(superclassCommand);
    180             checkReplyPacket(superclassReply, "ClassType.Superclass");
    181             classLoaderClassRefTypeID = superclassReply.getNextValueAsClassID();
    182         }
    183 
    184         // None of the superclasses was java.lang.ClassLoader, so it's not a classloader.
    185         return false;
    186     }
    187 }
    188