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